diff --git a/Android.mk b/Android.mk index c3e065c8baa8872a3f60cd9d97413e8f9c0b84ae..1388b0133e1a4c1ebe5056e038d23459d1e7a8f2 100644 --- a/Android.mk +++ b/Android.mk @@ -1,11 +1,9 @@ # Local modifications: -# * b/31757757 Precompiled proto classes have been included. # * removed com.google.android.backup.api_key. This should be added to # the manifest in the top level directory. # * removed com.google.android.geo.API_KEY key. This should be added to # the manifest files in java/com/android/incallui/calllocation/impl/ # and /java/com/android/incallui/maps/impl/ -# * b/35391680 apache temporarily included in the top level directory. LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -20,7 +18,6 @@ BASE_DIR := java/com/android # Primary dialer module sources. SRC_DIRS := \ - apache \ $(BASE_DIR)/contacts/common \ $(BASE_DIR)/dialer \ $(BASE_DIR)/incallui \ @@ -44,12 +41,17 @@ EXCLUDE_FILES := \ $(BASE_DIR)/incallui/maps/impl/MapsModule.java \ $(BASE_DIR)/incallui/maps/impl/StaticMapFragment.java +# Exclude testing only class, not used anywhere here +EXCLUDE_FILES += \ + $(BASE_DIR)/contacts/common/format/testing/SpannedTestUtils.java + # All Dialers resources. # find . -type d -name "res" | uniq | sort RES_DIRS := \ assets/product/res \ assets/quantum/res \ $(BASE_DIR)/contacts/common/res \ + $(BASE_DIR)/dialer/about/res \ $(BASE_DIR)/dialer/app/res \ $(BASE_DIR)/dialer/app/voicemail/error/res \ $(BASE_DIR)/dialer/blocking/res \ @@ -57,8 +59,10 @@ RES_DIRS := \ $(BASE_DIR)/dialer/callcomposer/cameraui/res \ $(BASE_DIR)/dialer/callcomposer/res \ $(BASE_DIR)/dialer/calldetails/res \ + $(BASE_DIR)/dialer/calllog/ui/res \ $(BASE_DIR)/dialer/calllogutils/res \ $(BASE_DIR)/dialer/common/res \ + $(BASE_DIR)/dialer/contactsfragment/res \ $(BASE_DIR)/dialer/dialpadview/res \ $(BASE_DIR)/dialer/interactions/res \ $(BASE_DIR)/dialer/notification/res \ @@ -84,16 +88,18 @@ RES_DIRS := \ $(BASE_DIR)/incallui/incall/impl/res \ $(BASE_DIR)/incallui/res \ $(BASE_DIR)/incallui/sessiondata/res \ + $(BASE_DIR)/incallui/telecomeventui/res \ $(BASE_DIR)/incallui/video/impl/res \ $(BASE_DIR)/incallui/video/protocol/res \ $(BASE_DIR)/incallui/wifi/res \ - $(BASE_DIR)/voicemail/impl/res + $(BASE_DIR)/voicemail/impl/res \ # Dialer manifest files to merge. # find . -type f -name "AndroidManifest.xml" | uniq | sort DIALER_MANIFEST_FILES += \ $(BASE_DIR)/contacts/common/AndroidManifest.xml \ + $(BASE_DIR)/dialer/about/AndroidManifest.xml \ $(BASE_DIR)/dialer/app/AndroidManifest.xml \ $(BASE_DIR)/dialer/app/manifests/activities/AndroidManifest.xml \ $(BASE_DIR)/dialer/app/voicemail/error/AndroidManifest.xml \ @@ -104,8 +110,10 @@ DIALER_MANIFEST_FILES += \ $(BASE_DIR)/dialer/callcomposer/camera/camerafocus/AndroidManifest.xml \ $(BASE_DIR)/dialer/callcomposer/cameraui/AndroidManifest.xml \ $(BASE_DIR)/dialer/calldetails/AndroidManifest.xml \ + $(BASE_DIR)/dialer/calllog/ui/AndroidManifest.xml \ $(BASE_DIR)/dialer/calllogutils/AndroidManifest.xml \ $(BASE_DIR)/dialer/common/AndroidManifest.xml \ + $(BASE_DIR)/dialer/contactsfragment/AndroidManifest.xml \ $(BASE_DIR)/dialer/dialpadview/AndroidManifest.xml \ $(BASE_DIR)/dialer/interactions/AndroidManifest.xml \ $(BASE_DIR)/dialer/notification/AndroidManifest.xml \ @@ -131,10 +139,11 @@ DIALER_MANIFEST_FILES += \ $(BASE_DIR)/incallui/hold/AndroidManifest.xml \ $(BASE_DIR)/incallui/incall/impl/AndroidManifest.xml \ $(BASE_DIR)/incallui/sessiondata/AndroidManifest.xml \ + $(BASE_DIR)/incallui/telecomeventui/AndroidManifest.xml \ $(BASE_DIR)/incallui/video/impl/AndroidManifest.xml \ $(BASE_DIR)/incallui/video/protocol/AndroidManifest.xml \ $(BASE_DIR)/incallui/wifi/AndroidManifest.xml \ - $(BASE_DIR)/voicemail/impl/AndroidManifest.xml + $(BASE_DIR)/voicemail/impl/AndroidManifest.xml \ # Merge all manifest files. @@ -142,12 +151,9 @@ LOCAL_FULL_LIBS_MANIFEST_FILES := \ $(addprefix $(LOCAL_PATH)/, $(DIALER_MANIFEST_FILES)) LOCAL_SRC_FILES := $(call all-java-files-under, $(SRC_DIRS)) LOCAL_SRC_FILES := $(filter-out $(EXCLUDE_FILES),$(LOCAL_SRC_FILES)) -# Native protobuf compilation disabled b/36564333 -# Include protocol buffers and use the nano compiler. -# LOCAL_SRC_FILES += $(call all-proto-files-under, $(SRC_DIRS)) -# LOCAL_PROTOC_OPTIMIZE_TYPE := nano -# LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH) -# LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java,generate_clear=true,store_unknown_fields=true,generate_equals=true +LOCAL_SRC_FILES += $(call all-proto-files-under, $(SRC_DIRS)) +LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH) + LOCAL_RESOURCE_DIR := \ $(addprefix $(LOCAL_PATH)/, $(RES_DIRS)) \ $(support_library_root_dir)/design/res \ @@ -159,12 +165,8 @@ LOCAL_RESOURCE_DIR := \ # We specify each package explicitly to glob resource files. LOCAL_AAPT_FLAGS := \ --auto-add-overlay \ - --extra-packages android.support.design \ - --extra-packages android.support.transition \ - --extra-packages android.support.v7.appcompat \ - --extra-packages android.support.v7.cardview \ - --extra-packages android.support.v7.recyclerview \ --extra-packages com.android.contacts.common \ + --extra-packages com.android.dialer.about \ --extra-packages com.android.dialer.app \ --extra-packages com.android.dialer.app.voicemail.error \ --extra-packages com.android.dialer.blocking \ @@ -174,8 +176,10 @@ LOCAL_AAPT_FLAGS := \ --extra-packages com.android.dialer.callcomposer.camera.camerafocus \ --extra-packages com.android.dialer.callcomposer.cameraui \ --extra-packages com.android.dialer.calldetails \ + --extra-packages com.android.dialer.calllog.ui \ --extra-packages com.android.dialer.calllogutils \ --extra-packages com.android.dialer.common \ + --extra-packages com.android.dialer.contactsfragment \ --extra-packages com.android.dialer.dialpadview \ --extra-packages com.android.dialer.interactions \ --extra-packages com.android.dialer.notification \ @@ -184,6 +188,7 @@ LOCAL_AAPT_FLAGS := \ --extra-packages com.android.dialer.postcall \ --extra-packages com.android.dialer.shortcuts \ --extra-packages com.android.dialer.speeddial \ + --extra-packages com.android.dialer.theme \ --extra-packages com.android.dialer.util \ --extra-packages com.android.dialer.voicemailstatus \ --extra-packages com.android.dialer.widget \ @@ -203,6 +208,7 @@ LOCAL_AAPT_FLAGS := \ --extra-packages com.android.incallui.incall.impl \ --extra-packages com.android.incallui.maps.impl \ --extra-packages com.android.incallui.sessiondata \ + --extra-packages com.android.incallui.telecomeventui \ --extra-packages com.android.incallui.video \ --extra-packages com.android.incallui.video.impl \ --extra-packages com.android.incallui.wifi \ @@ -216,13 +222,6 @@ LOCAL_AAPT_FLAGS := \ LOCAL_STATIC_JAVA_LIBRARIES := \ android-common \ - android-support-design \ - android-support-transition \ - android-support-v13 \ - android-support-v4 \ - android-support-v7-appcompat \ - android-support-v7-cardview \ - android-support-v7-recyclerview \ com.android.vcard \ dialer-commons-io-target \ dialer-dagger2-target \ @@ -233,11 +232,21 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ dialer-javax-annotation-api-target \ dialer-javax-inject-target \ dialer-libshortcutbadger-target \ + dialer-mime4j-core-target \ + dialer-mime4j-dom-target \ jsr305 \ libphonenumber \ - libprotobuf-java-nano \ volley \ +LOCAL_STATIC_ANDROID_LIBRARIES := \ + android-support-design \ + android-support-transition \ + android-support-v13 \ + android-support-v4 \ + android-support-v7-appcompat \ + android-support-v7-cardview \ + android-support-v7-recyclerview \ + LOCAL_JAVA_LIBRARIES := \ org.apache.http.legacy \ dialer-auto-value \ @@ -279,6 +288,11 @@ LOCAL_MODULE_TAGS := optional LOCAL_PACKAGE_NAME := Dialer LOCAL_CERTIFICATE := shared LOCAL_PRIVILEGED_MODULE := true +LOCAL_USE_AAPT2 := true + +# b/37483961 - Jack Not Compiling Dagger Class Properly +LOCAL_JACK_ENABLED := javac_frontend + include $(BUILD_PACKAGE) # Cleanup local state @@ -294,10 +308,10 @@ PROCESSOR_JARS := include $(CLEAR_VARS) LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ - dialer-dagger2-compiler:../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger-compiler/2.6/dagger-compiler-2.6$(COMMON_JAVA_PACKAGE_SUFFIX) \ + dialer-dagger2-compiler:../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger-compiler/2.7/dagger-compiler-2.7$(COMMON_JAVA_PACKAGE_SUFFIX) \ dialer-auto-value:../../../prebuilts/tools/common/m2/repository/com/google/auto/value/auto-value/1.3/auto-value-1.3$(COMMON_JAVA_PACKAGE_SUFFIX) \ - dialer-dagger2:../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger/2.6/dagger-2.6$(COMMON_JAVA_PACKAGE_SUFFIX) \ - dialer-dagger2-producers:../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger-producers/2.6/dagger-producers-2.6$(COMMON_JAVA_PACKAGE_SUFFIX) \ + dialer-dagger2:../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger/2.7/dagger-2.7$(COMMON_JAVA_PACKAGE_SUFFIX) \ + dialer-dagger2-producers:../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger-producers/2.7/dagger-producers-2.7$(COMMON_JAVA_PACKAGE_SUFFIX) \ dialer-guava:../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/20.0/guava-20.0$(COMMON_JAVA_PACKAGE_SUFFIX) \ dialer-javax-annotation-api:../../../prebuilts/tools/common/m2/repository/javax/annotation/javax.annotation-api/1.2/javax.annotation-api-1.2$(COMMON_JAVA_PACKAGE_SUFFIX) \ dialer-javax-inject:../../../prebuilts/tools/common/m2/repository/javax/inject/javax.inject/1/javax.inject-1$(COMMON_JAVA_PACKAGE_SUFFIX) @@ -321,7 +335,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE := dialer-dagger2-target LOCAL_SDK_VERSION := current -LOCAL_SRC_FILES := ../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger/2.6/dagger-2.6$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_SRC_FILES := ../../../prebuilts/tools/common/m2/repository/com/google/dagger/dagger/2.7/dagger-2.7$(COMMON_JAVA_PACKAGE_SUFFIX) LOCAL_UNINSTALLABLE_MODULE := true include $(BUILD_PREBUILT) @@ -388,8 +402,6 @@ include $(BUILD_PREBUILT) include $(CLEAR_VARS) -include $(CLEAR_VARS) - LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE := dialer-commons-io-target LOCAL_SDK_VERSION := current @@ -399,3 +411,23 @@ LOCAL_UNINSTALLABLE_MODULE := true include $(BUILD_PREBUILT) include $(CLEAR_VARS) + +LOCAL_MODULE_CLASS := JAVA_LIBRARIES +LOCAL_MODULE := dialer-mime4j-core-target +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := ../../../prebuilts/tools/common/m2/repository/org/apache/james/apache-mime4j-core/0.7.2/apache-mime4j-core-0.7.2$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_UNINSTALLABLE_MODULE := true + +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) + +LOCAL_MODULE_CLASS := JAVA_LIBRARIES +LOCAL_MODULE := dialer-mime4j-dom-target +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := ../../../prebuilts/tools/common/m2/repository/org/apache/james/apache-mime4j-dom/0.7.2/apache-mime4j-dom-0.7.2$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_UNINSTALLABLE_MODULE := true + +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) \ No newline at end of file diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 022cb174a687716b764c08b97cdc727dc1d88f40..c04f8bec98a71ef940fc1d61867bac9902f12bee 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -21,7 +21,7 @@ + android:targetSdkVersion="26"/> diff --git a/apache/org/apache/james/mime4j/BodyDescriptor.java b/apache/org/apache/james/mime4j/BodyDescriptor.java deleted file mode 100644 index 867c43d86d28154f0aea5f4e5ddaea4d35b4be1c..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/BodyDescriptor.java +++ /dev/null @@ -1,392 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import java.util.HashMap; -import java.util.Map; - -/** - * Encapsulates the values of the MIME-specific header fields - * (which starts with Content-). - * - * - * @version $Id: BodyDescriptor.java,v 1.4 2005/02/11 10:08:37 ntherning Exp $ - */ -public class BodyDescriptor { - private static Log log = LogFactory.getLog(BodyDescriptor.class); - - private String mimeType = "text/plain"; - private String boundary = null; - private String charset = "us-ascii"; - private String transferEncoding = "7bit"; - private Map parameters = new HashMap(); - private boolean contentTypeSet = false; - private boolean contentTransferEncSet = false; - - /** - * Creates a new root BodyDescriptor instance. - */ - public BodyDescriptor() { - this(null); - } - - /** - * Creates a new BodyDescriptor instance. - * - * @param parent the descriptor of the parent or null if this - * is the root descriptor. - */ - public BodyDescriptor(BodyDescriptor parent) { - if (parent != null && parent.isMimeType("multipart/digest")) { - mimeType = "message/rfc822"; - } else { - mimeType = "text/plain"; - } - } - - /** - * Should be called for each Content- header field of - * a MIME message or part. - * - * @param name the field name. - * @param value the field value. - */ - public void addField(String name, String value) { - - name = name.trim().toLowerCase(); - - if (name.equals("content-transfer-encoding") && !contentTransferEncSet) { - contentTransferEncSet = true; - - value = value.trim().toLowerCase(); - if (value.length() > 0) { - transferEncoding = value; - } - - } else if (name.equals("content-type") && !contentTypeSet) { - contentTypeSet = true; - - value = value.trim(); - - /* - * Unfold Content-Type value - */ - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (c == '\r' || c == '\n') { - continue; - } - sb.append(c); - } - - Map params = getHeaderParams(sb.toString()); - - String main = params.get(""); - if (main != null) { - main = main.toLowerCase().trim(); - int index = main.indexOf('/'); - boolean valid = false; - if (index != -1) { - String type = main.substring(0, index).trim(); - String subtype = main.substring(index + 1).trim(); - if (type.length() > 0 && subtype.length() > 0) { - main = type + "/" + subtype; - valid = true; - } - } - - if (!valid) { - main = null; - } - } - String b = params.get("boundary"); - - if (main != null - && ((main.startsWith("multipart/") && b != null) - || !main.startsWith("multipart/"))) { - - mimeType = main; - } - - if (isMultipart()) { - boundary = b; - } - - String c = params.get("charset"); - if (c != null) { - c = c.trim(); - if (c.length() > 0) { - charset = c.toLowerCase(); - } - } - - /* - * Add all other parameters to parameters. - */ - parameters.putAll(params); - parameters.remove(""); - parameters.remove("boundary"); - parameters.remove("charset"); - } - } - - private Map getHeaderParams(String headerValue) { - Map result = new HashMap(); - - // split main value and parameters - String main; - String rest; - if (headerValue.indexOf(";") == -1) { - main = headerValue; - rest = null; - } else { - main = headerValue.substring(0, headerValue.indexOf(";")); - rest = headerValue.substring(main.length() + 1); - } - - result.put("", main); - if (rest != null) { - char[] chars = rest.toCharArray(); - StringBuffer paramName = new StringBuffer(); - StringBuffer paramValue = new StringBuffer(); - - final byte READY_FOR_NAME = 0; - final byte IN_NAME = 1; - final byte READY_FOR_VALUE = 2; - final byte IN_VALUE = 3; - final byte IN_QUOTED_VALUE = 4; - final byte VALUE_DONE = 5; - final byte ERROR = 99; - - byte state = READY_FOR_NAME; - boolean escaped = false; - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - - switch (state) { - case ERROR: - if (c == ';') - state = READY_FOR_NAME; - break; - - case READY_FOR_NAME: - if (c == '=') { - log.error("Expected header param name, got '='"); - state = ERROR; - break; - } - - paramName = new StringBuffer(); - paramValue = new StringBuffer(); - - state = IN_NAME; - // $FALL-THROUGH$ - - case IN_NAME: - if (c == '=') { - if (paramName.length() == 0) - state = ERROR; - else - state = READY_FOR_VALUE; - break; - } - - // not '='... just add to name - paramName.append(c); - break; - - case READY_FOR_VALUE: - boolean fallThrough = false; - switch (c) { - case ' ': - case '\t': - break; // ignore spaces, especially before '"' - - case '"': - state = IN_QUOTED_VALUE; - break; - - default: - state = IN_VALUE; - fallThrough = true; - break; - } - if (!fallThrough) - break; - - // $FALL-THROUGH$ - - case IN_VALUE: - fallThrough = false; - switch (c) { - case ';': - case ' ': - case '\t': - result.put( - paramName.toString().trim().toLowerCase(), - paramValue.toString().trim()); - state = VALUE_DONE; - fallThrough = true; - break; - default: - paramValue.append(c); - break; - } - if (!fallThrough) - break; - - // $FALL-THROUGH$ - - case VALUE_DONE: - switch (c) { - case ';': - state = READY_FOR_NAME; - break; - - case ' ': - case '\t': - break; - - default: - state = ERROR; - break; - } - break; - - case IN_QUOTED_VALUE: - switch (c) { - case '"': - if (!escaped) { - // don't trim quoted strings; the spaces could be intentional. - result.put( - paramName.toString().trim().toLowerCase(), - paramValue.toString()); - state = VALUE_DONE; - } else { - escaped = false; - paramValue.append(c); - } - break; - - case '\\': - if (escaped) { - paramValue.append('\\'); - } - escaped = !escaped; - break; - - default: - if (escaped) { - paramValue.append('\\'); - } - escaped = false; - paramValue.append(c); - break; - } - break; - - } - } - - // done looping. check if anything is left over. - if (state == IN_VALUE) { - result.put( - paramName.toString().trim().toLowerCase(), - paramValue.toString().trim()); - } - } - - return result; - } - - - public boolean isMimeType(String mimeType) { - return this.mimeType.equals(mimeType.toLowerCase()); - } - - /** - * Return true if the BodyDescriptor belongs to a message - */ - public boolean isMessage() { - return mimeType.equals("message/rfc822"); - } - - /** - * Return true if the BodyDescripotro belongs to a multipart - */ - public boolean isMultipart() { - return mimeType.startsWith("multipart/"); - } - - /** - * Return the MimeType - */ - public String getMimeType() { - return mimeType; - } - - /** - * Return the boundary - */ - public String getBoundary() { - return boundary; - } - - /** - * Return the charset - */ - public String getCharset() { - return charset; - } - - /** - * Return all parameters for the BodyDescriptor - */ - public Map getParameters() { - return parameters; - } - - /** - * Return the TransferEncoding - */ - public String getTransferEncoding() { - return transferEncoding; - } - - /** - * Return true if it's base64 encoded - */ - public boolean isBase64Encoded() { - return "base64".equals(transferEncoding); - } - - /** - * Return true if it's quoted-printable - */ - public boolean isQuotedPrintableEncoded() { - return "quoted-printable".equals(transferEncoding); - } - - @Override - public String toString() { - return mimeType; - } -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/CloseShieldInputStream.java b/apache/org/apache/james/mime4j/CloseShieldInputStream.java deleted file mode 100644 index d9f3b078a105a01056b90efdb7983687acf3ef17..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/CloseShieldInputStream.java +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import java.io.InputStream; -import java.io.IOException; - -/** - * InputStream that shields its underlying input stream from - * being closed. - * - * - * @version $Id: CloseShieldInputStream.java,v 1.2 2004/10/02 12:41:10 ntherning Exp $ - */ -public class CloseShieldInputStream extends InputStream { - - /** - * Underlying InputStream - */ - private InputStream is; - - public CloseShieldInputStream(InputStream is) { - this.is = is; - } - - public InputStream getUnderlyingStream() { - return is; - } - - /** - * @see java.io.InputStream#read() - */ - public int read() throws IOException { - checkIfClosed(); - return is.read(); - } - - /** - * @see java.io.InputStream#available() - */ - public int available() throws IOException { - checkIfClosed(); - return is.available(); - } - - - /** - * Set the underlying InputStream to null - */ - public void close() throws IOException { - is = null; - } - - /** - * @see java.io.FilterInputStream#reset() - */ - public synchronized void reset() throws IOException { - checkIfClosed(); - is.reset(); - } - - /** - * @see java.io.FilterInputStream#markSupported() - */ - public boolean markSupported() { - if (is == null) - return false; - return is.markSupported(); - } - - /** - * @see java.io.FilterInputStream#mark(int) - */ - public synchronized void mark(int readlimit) { - if (is != null) - is.mark(readlimit); - } - - /** - * @see java.io.FilterInputStream#skip(long) - */ - public long skip(long n) throws IOException { - checkIfClosed(); - return is.skip(n); - } - - /** - * @see java.io.FilterInputStream#read(byte[]) - */ - public int read(byte b[]) throws IOException { - checkIfClosed(); - return is.read(b); - } - - /** - * @see java.io.FilterInputStream#read(byte[], int, int) - */ - public int read(byte b[], int off, int len) throws IOException { - checkIfClosed(); - return is.read(b, off, len); - } - - /** - * Check if the underlying InputStream is null. If so throw an Exception - * - * @throws IOException if the underlying InputStream is null - */ - private void checkIfClosed() throws IOException { - if (is == null) - throw new IOException("Stream is closed"); - } -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/ContentHandler.java b/apache/org/apache/james/mime4j/ContentHandler.java deleted file mode 100644 index b437e739e085a3d0059975aa83197198dd1334fd..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/ContentHandler.java +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import java.io.IOException; -import java.io.InputStream; - -/** - *

- * Receives notifications of the content of a plain RFC822 or MIME message. - * Implement this interface and register an instance of that implementation - * with a MimeStreamParser instance using its - * {@link org.apache.james.mime4j.MimeStreamParser#setContentHandler(ContentHandler)} - * method. The parser uses the ContentHandler instance to report - * basic message-related events like the start and end of the body of a - * part in a multipart MIME entity. - *

- *

- * Events will be generated in the order the corresponding elements occur in - * the message stream parsed by the parser. E.g.: - *

- *      startMessage()
- *          startHeader()
- *              field(...)
- *              field(...)
- *              ...
- *          endHeader()
- *          startMultipart()
- *              preamble(...)
- *              startBodyPart()
- *                  startHeader()
- *                      field(...)
- *                      field(...)
- *                      ...
- *                  endHeader()
- *                  body()
- *              endBodyPart()
- *              startBodyPart()
- *                  startHeader()
- *                      field(...)
- *                      field(...)
- *                      ...
- *                  endHeader()
- *                  body()
- *              endBodyPart()
- *              epilogue(...)
- *          endMultipart()
- *      endMessage()
- * 
- * The above shows an example of a MIME message consisting of a multipart - * body containing two body parts. - *

- *

- * See MIME RFCs 2045-2049 for more information on the structure of MIME - * messages and RFC 822 and 2822 for the general structure of Internet mail - * messages. - *

- * - * - * @version $Id: ContentHandler.java,v 1.3 2004/10/02 12:41:10 ntherning Exp $ - */ -public interface ContentHandler { - /** - * Called when a new message starts (a top level message or an embedded - * rfc822 message). - */ - void startMessage(); - - /** - * Called when a message ends. - */ - void endMessage(); - - /** - * Called when a new body part starts inside a - * multipart/* entity. - */ - void startBodyPart(); - - /** - * Called when a body part ends. - */ - void endBodyPart(); - - /** - * Called when a header (of a message or body part) is about to be parsed. - */ - void startHeader(); - - /** - * Called for each field of a header. - * - * @param fieldData the raw contents of the field - * (Field-Name: field value). The value will not be - * unfolded. - */ - void field(String fieldData); - - /** - * Called when there are no more header fields in a message or body part. - */ - void endHeader(); - - /** - * Called for the preamble (whatever comes before the first body part) - * of a multipart/* entity. - * - * @param is used to get the contents of the preamble. - * @throws IOException should be thrown on I/O errors. - */ - void preamble(InputStream is) throws IOException; - - /** - * Called for the epilogue (whatever comes after the final body part) - * of a multipart/* entity. - * - * @param is used to get the contents of the epilogue. - * @throws IOException should be thrown on I/O errors. - */ - void epilogue(InputStream is) throws IOException; - - /** - * Called when the body of a multipart entity is about to be parsed. - * - * @param bd encapsulates the values (either read from the - * message stream or, if not present, determined implictly - * as described in the - * MIME rfc:s) of the Content-Type and - * Content-Transfer-Encoding header fields. - */ - void startMultipart(BodyDescriptor bd); - - /** - * Called when the body of an entity has been parsed. - */ - void endMultipart(); - - /** - * Called when the body of a discrete (non-multipart) entity is about to - * be parsed. - * - * @param bd see {@link #startMultipart(BodyDescriptor)} - * @param is the contents of the body. NOTE: this is the raw body contents - * - it will not be decoded if encoded. The bd - * parameter should be used to determine how the stream data - * should be decoded. - * @throws IOException should be thrown on I/O errors. - */ - void body(BodyDescriptor bd, InputStream is) throws IOException; - - /** - * Called when a new entity (message or body part) starts and the - * parser is in raw mode. - * - * @param is the raw contents of the entity. - * @throws IOException should be thrown on I/O errors. - * @see MimeStreamParser#setRaw(boolean) - */ - void raw(InputStream is) throws IOException; -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/EOLConvertingInputStream.java b/apache/org/apache/james/mime4j/EOLConvertingInputStream.java deleted file mode 100644 index d6ef706b20d891db0ffd8d8f2ea674dae448b951..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/EOLConvertingInputStream.java +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import java.io.IOException; -import java.io.InputStream; -import java.io.PushbackInputStream; - -/** - * InputStream which converts \r - * bytes not followed by \n and \n not - * preceded by \r to \r\n. - * - * - * @version $Id: EOLConvertingInputStream.java,v 1.4 2004/11/29 13:15:42 ntherning Exp $ - */ -public class EOLConvertingInputStream extends InputStream { - /** Converts single '\r' to '\r\n' */ - public static final int CONVERT_CR = 1; - /** Converts single '\n' to '\r\n' */ - public static final int CONVERT_LF = 2; - /** Converts single '\r' and '\n' to '\r\n' */ - public static final int CONVERT_BOTH = 3; - - private PushbackInputStream in = null; - private int previous = 0; - private int flags = CONVERT_BOTH; - private int size = 0; - private int pos = 0; - private int nextTenPctPos; - private int tenPctSize; - private Callback callback; - - public interface Callback { - public void report(int bytesRead); - } - - /** - * Creates a new EOLConvertingInputStream - * instance converting bytes in the given InputStream. - * The flag CONVERT_BOTH is the default. - * - * @param in the InputStream to read from. - */ - public EOLConvertingInputStream(InputStream _in) { - super(); - in = new PushbackInputStream(_in, 2); - } - - /** - * Creates a new EOLConvertingInputStream - * instance converting bytes in the given InputStream. - * - * @param _in the InputStream to read from. - * @param _size the size of the input stream (need not be exact) - * @param _callback a callback reporting when each 10% of stream's size is reached - */ - public EOLConvertingInputStream(InputStream _in, int _size, Callback _callback) { - this(_in); - size = _size; - tenPctSize = size / 10; - nextTenPctPos = tenPctSize; - callback = _callback; - } - - /** - * Closes the underlying stream. - * - * @throws IOException on I/O errors. - */ - public void close() throws IOException { - in.close(); - } - - private int readByte() throws IOException { - int b = in.read(); - if (b != -1) { - if (callback != null && pos++ == nextTenPctPos) { - nextTenPctPos += tenPctSize; - if (callback != null) { - callback.report(pos); - } - } - } - return b; - } - - private void unreadByte(int c) throws IOException { - in.unread(c); - pos--; - } - - /** - * @see java.io.InputStream#read() - */ - public int read() throws IOException { - int b = readByte(); - - if (b == -1) { - pos = size; - return -1; - } - - if ((flags & CONVERT_CR) != 0 && b == '\r') { - int c = readByte(); - if (c != -1) { - unreadByte(c); - } - if (c != '\n') { - unreadByte('\n'); - } - } else if ((flags & CONVERT_LF) != 0 && b == '\n' && previous != '\r') { - b = '\r'; - unreadByte('\n'); - } - - previous = b; - - return b; - } - -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/Log.java b/apache/org/apache/james/mime4j/Log.java deleted file mode 100644 index 5eeead5f3e682ac379e2b52b0bba5173b09156d7..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/Log.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2009 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 org.apache.james.mime4j; - -/** - * Empty stub for the apache logging library. - */ -public class Log { - private static final String LOG_TAG = "Email Log"; - - public Log(Class mClazz) { - } - - public boolean isDebugEnabled() { - return false; - } - - public boolean isErrorEnabled() { - return true; - } - - public boolean isFatalEnabled() { - return true; - } - - public boolean isInfoEnabled() { - return false; - } - - public boolean isTraceEnabled() { - return false; - } - - public boolean isWarnEnabled() { - return true; - } - - public void trace(Object message) { - if (!isTraceEnabled()) return; - android.util.Log.v(LOG_TAG, toString(message, null)); - } - - public void trace(Object message, Throwable t) { - if (!isTraceEnabled()) return; - android.util.Log.v(LOG_TAG, toString(message, t)); - } - - public void debug(Object message) { - if (!isDebugEnabled()) return; - android.util.Log.d(LOG_TAG, toString(message, null)); - } - - public void debug(Object message, Throwable t) { - if (!isDebugEnabled()) return; - android.util.Log.d(LOG_TAG, toString(message, t)); - } - - public void info(Object message) { - if (!isInfoEnabled()) return; - android.util.Log.i(LOG_TAG, toString(message, null)); - } - - public void info(Object message, Throwable t) { - if (!isInfoEnabled()) return; - android.util.Log.i(LOG_TAG, toString(message, t)); - } - - public void warn(Object message) { - android.util.Log.w(LOG_TAG, toString(message, null)); - } - - public void warn(Object message, Throwable t) { - android.util.Log.w(LOG_TAG, toString(message, t)); - } - - public void error(Object message) { - android.util.Log.e(LOG_TAG, toString(message, null)); - } - - public void error(Object message, Throwable t) { - android.util.Log.e(LOG_TAG, toString(message, t)); - } - - public void fatal(Object message) { - android.util.Log.e(LOG_TAG, toString(message, null)); - } - - public void fatal(Object message, Throwable t) { - android.util.Log.e(LOG_TAG, toString(message, t)); - } - - private static String toString(Object o, Throwable t) { - String m = (o == null) ? "(null)" : o.toString(); - if (t == null) { - return m; - } else { - return m + " " + t.getMessage(); - } - } -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/LogFactory.java b/apache/org/apache/james/mime4j/LogFactory.java deleted file mode 100644 index ed6e3de3d7ea20167c60d958e8fa52b8fcfa0a5e..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/LogFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2009 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 org.apache.james.mime4j; - -/** - * Empty stub for the apache logging library. - */ -public final class LogFactory { - private LogFactory() { - } - - public static Log getLog(Class clazz) { - return new Log(clazz); - } -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/MimeBoundaryInputStream.java b/apache/org/apache/james/mime4j/MimeBoundaryInputStream.java deleted file mode 100644 index c6d6f248a0ebc3d4add4ef997fd10773537d2ba2..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/MimeBoundaryInputStream.java +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import java.io.IOException; -import java.io.InputStream; -import java.io.PushbackInputStream; - -/** - * Stream that constrains itself to a single MIME body part. - * After the stream ends (i.e. read() returns -1) {@link #hasMoreParts()} - * can be used to determine if a final boundary has been seen or not. - * If {@link #parentEOF()} is true an unexpected end of stream - * has been detected in the parent stream. - * - * - * - * @version $Id: MimeBoundaryInputStream.java,v 1.2 2004/11/29 13:15:42 ntherning Exp $ - */ -public class MimeBoundaryInputStream extends InputStream { - - private PushbackInputStream s = null; - private byte[] boundary = null; - private boolean first = true; - private boolean eof = false; - private boolean parenteof = false; - private boolean moreParts = true; - - /** - * Creates a new MimeBoundaryInputStream. - * @param s The underlying stream. - * @param boundary Boundary string (not including leading hyphens). - */ - public MimeBoundaryInputStream(InputStream s, String boundary) - throws IOException { - - this.s = new PushbackInputStream(s, boundary.length() + 4); - - boundary = "--" + boundary; - this.boundary = new byte[boundary.length()]; - for (int i = 0; i < this.boundary.length; i++) { - this.boundary[i] = (byte) boundary.charAt(i); - } - - /* - * By reading one byte we will update moreParts to be as expected - * before any bytes have been read. - */ - int b = read(); - if (b != -1) { - this.s.unread(b); - } - } - - /** - * Closes the underlying stream. - * - * @throws IOException on I/O errors. - */ - public void close() throws IOException { - s.close(); - } - - /** - * Determines if the underlying stream has more parts (this stream has - * not seen an end boundary). - * - * @return true if there are more parts in the underlying - * stream, false otherwise. - */ - public boolean hasMoreParts() { - return moreParts; - } - - /** - * Determines if the parent stream has reached EOF - * - * @return true if EOF has been reached for the parent stream, - * false otherwise. - */ - public boolean parentEOF() { - return parenteof; - } - - /** - * Consumes all unread bytes of this stream. After a call to this method - * this stream will have reached EOF. - * - * @throws IOException on I/O errors. - */ - public void consume() throws IOException { - while (read() != -1) { - } - } - - /** - * @see java.io.InputStream#read() - */ - public int read() throws IOException { - if (eof) { - return -1; - } - - if (first) { - first = false; - if (matchBoundary()) { - return -1; - } - } - - int b1 = s.read(); - int b2 = s.read(); - - if (b1 == '\r' && b2 == '\n') { - if (matchBoundary()) { - return -1; - } - } - - if (b2 != -1) { - s.unread(b2); - } - - parenteof = b1 == -1; - eof = parenteof; - - return b1; - } - - private boolean matchBoundary() throws IOException { - - for (int i = 0; i < boundary.length; i++) { - int b = s.read(); - if (b != boundary[i]) { - if (b != -1) { - s.unread(b); - } - for (int j = i - 1; j >= 0; j--) { - s.unread(boundary[j]); - } - return false; - } - } - - /* - * We have a match. Is it an end boundary? - */ - int prev = s.read(); - int curr = s.read(); - moreParts = !(prev == '-' && curr == '-'); - do { - if (curr == '\n' && prev == '\r') { - break; - } - prev = curr; - } while ((curr = s.read()) != -1); - - if (curr == -1) { - moreParts = false; - parenteof = true; - } - - eof = true; - - return true; - } -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/MimeStreamParser.java b/apache/org/apache/james/mime4j/MimeStreamParser.java deleted file mode 100644 index a8aad5a38c8e5f0a83386ca0cac31f8a295743aa..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/MimeStreamParser.java +++ /dev/null @@ -1,324 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import org.apache.james.mime4j.decoder.Base64InputStream; -import org.apache.james.mime4j.decoder.QuotedPrintableInputStream; - -import java.io.IOException; -import java.io.InputStream; -import java.util.BitSet; -import java.util.LinkedList; - -/** - *

- * Parses MIME (or RFC822) message streams of bytes or characters and reports - * parsing events to a ContentHandler instance. - *

- *

- * Typical usage:
- *

- *      ContentHandler handler = new MyHandler();
- *      MimeStreamParser parser = new MimeStreamParser();
- *      parser.setContentHandler(handler);
- *      parser.parse(new BufferedInputStream(new FileInputStream("mime.msg")));
- * 
- * NOTE: All lines must end with CRLF - * (\r\n). If you are unsure of the line endings in your stream - * you should wrap it in a {@link org.apache.james.mime4j.EOLConvertingInputStream} instance. - * - * - * @version $Id: MimeStreamParser.java,v 1.8 2005/02/11 10:12:02 ntherning Exp $ - */ -public class MimeStreamParser { - private static final Log log = LogFactory.getLog(MimeStreamParser.class); - - private static BitSet fieldChars = null; - - private RootInputStream rootStream = null; - private LinkedList bodyDescriptors = new LinkedList(); - private ContentHandler handler = null; - private boolean raw = false; - private boolean prematureEof = false; - - static { - fieldChars = new BitSet(); - for (int i = 0x21; i <= 0x39; i++) { - fieldChars.set(i); - } - for (int i = 0x3b; i <= 0x7e; i++) { - fieldChars.set(i); - } - } - - /** - * Creates a new MimeStreamParser instance. - */ - public MimeStreamParser() { - } - - /** - * Parses a stream of bytes containing a MIME message. - * - * @param is the stream to parse. - * @throws IOException on I/O errors. - */ - public void parse(InputStream is) throws IOException { - rootStream = new RootInputStream(is); - parseMessage(rootStream); - } - - /** - * Determines if this parser is currently in raw mode. - * - * @return true if in raw mode, false - * otherwise. - * @see #setRaw(boolean) - */ - public boolean isRaw() { - return raw; - } - - /** - * Enables or disables raw mode. In raw mode all future entities - * (messages or body parts) in the stream will be reported to the - * {@link ContentHandler#raw(InputStream)} handler method only. - * The stream will contain the entire unparsed entity contents - * including header fields and whatever is in the body. - * - * @param raw true enables raw mode, false - * disables it. - */ - public void setRaw(boolean raw) { - this.raw = raw; - } - - /** - * Finishes the parsing and stops reading lines. - * NOTE: No more lines will be parsed but the parser - * will still call - * {@link ContentHandler#endMultipart()}, - * {@link ContentHandler#endBodyPart()}, - * {@link ContentHandler#endMessage()}, etc to match previous calls - * to - * {@link ContentHandler#startMultipart(BodyDescriptor)}, - * {@link ContentHandler#startBodyPart()}, - * {@link ContentHandler#startMessage()}, etc. - */ - public void stop() { - rootStream.truncate(); - } - - /** - * Parses an entity which consists of a header followed by a body containing - * arbitrary data, body parts or an embedded message. - * - * @param is the stream to parse. - * @throws IOException on I/O errors. - */ - private void parseEntity(InputStream is) throws IOException { - BodyDescriptor bd = parseHeader(is); - - if (bd.isMultipart()) { - bodyDescriptors.addFirst(bd); - - handler.startMultipart(bd); - - MimeBoundaryInputStream tempIs = - new MimeBoundaryInputStream(is, bd.getBoundary()); - handler.preamble(new CloseShieldInputStream(tempIs)); - tempIs.consume(); - - while (tempIs.hasMoreParts()) { - tempIs = new MimeBoundaryInputStream(is, bd.getBoundary()); - parseBodyPart(tempIs); - tempIs.consume(); - if (tempIs.parentEOF()) { - prematureEof = true; -// if (log.isWarnEnabled()) { -// log.warn("Line " + rootStream.getLineNumber() -// + ": Body part ended prematurely. " -// + "Higher level boundary detected or " -// + "EOF reached."); -// } - break; - } - } - - handler.epilogue(new CloseShieldInputStream(is)); - - handler.endMultipart(); - - bodyDescriptors.removeFirst(); - - } else if (bd.isMessage()) { - if (bd.isBase64Encoded()) { - log.warn("base64 encoded message/rfc822 detected"); - is = new EOLConvertingInputStream( - new Base64InputStream(is)); - } else if (bd.isQuotedPrintableEncoded()) { - log.warn("quoted-printable encoded message/rfc822 detected"); - is = new EOLConvertingInputStream( - new QuotedPrintableInputStream(is)); - } - bodyDescriptors.addFirst(bd); - parseMessage(is); - bodyDescriptors.removeFirst(); - } else { - handler.body(bd, new CloseShieldInputStream(is)); - } - - /* - * Make sure the stream has been consumed. - */ - while (is.read() != -1) { - } - } - - private void parseMessage(InputStream is) throws IOException { - if (raw) { - handler.raw(new CloseShieldInputStream(is)); - } else { - handler.startMessage(); - parseEntity(is); - handler.endMessage(); - } - } - - public boolean getPrematureEof() { - return prematureEof; - } - - private void parseBodyPart(InputStream is) throws IOException { - if (raw) { - handler.raw(new CloseShieldInputStream(is)); - } else { - handler.startBodyPart(); - parseEntity(is); - handler.endBodyPart(); - } - } - - /** - * Parses a header. - * - * @param is the stream to parse. - * @return a BodyDescriptor describing the body following - * the header. - */ - private BodyDescriptor parseHeader(InputStream is) throws IOException { - BodyDescriptor bd = new BodyDescriptor(bodyDescriptors.isEmpty() - ? null : (BodyDescriptor) bodyDescriptors.getFirst()); - - handler.startHeader(); - - int lineNumber = rootStream.getLineNumber(); - - StringBuffer sb = new StringBuffer(); - int curr = 0; - int prev = 0; - while ((curr = is.read()) != -1) { - if (curr == '\n' && (prev == '\n' || prev == 0)) { - /* - * [\r]\n[\r]\n or an immediate \r\n have been seen. - */ - sb.deleteCharAt(sb.length() - 1); - break; - } - sb.append((char) curr); - prev = curr == '\r' ? prev : curr; - } - -// if (curr == -1 && log.isWarnEnabled()) { -// log.warn("Line " + rootStream.getLineNumber() -// + ": Unexpected end of headers detected. " -// + "Boundary detected in header or EOF reached."); -// } - - int start = 0; - int pos = 0; - int startLineNumber = lineNumber; - while (pos < sb.length()) { - while (pos < sb.length() && sb.charAt(pos) != '\r') { - pos++; - } - if (pos < sb.length() - 1 && sb.charAt(pos + 1) != '\n') { - pos++; - continue; - } - - if (pos >= sb.length() - 2 || fieldChars.get(sb.charAt(pos + 2))) { - - /* - * field should be the complete field data excluding the - * trailing \r\n. - */ - String field = sb.substring(start, pos); - start = pos + 2; - - /* - * Check for a valid field. - */ - int index = field.indexOf(':'); - boolean valid = false; - if (index != -1 && fieldChars.get(field.charAt(0))) { - valid = true; - String fieldName = field.substring(0, index).trim(); - for (int i = 0; i < fieldName.length(); i++) { - if (!fieldChars.get(fieldName.charAt(i))) { - valid = false; - break; - } - } - - if (valid) { - handler.field(field); - bd.addField(fieldName, field.substring(index + 1)); - } - } - - if (!valid && log.isWarnEnabled()) { - log.warn("Line " + startLineNumber - + ": Ignoring invalid field: '" + field.trim() + "'"); - } - - startLineNumber = lineNumber; - } - - pos += 2; - lineNumber++; - } - - handler.endHeader(); - - return bd; - } - - /** - * Sets the ContentHandler to use when reporting - * parsing events. - * - * @param h the ContentHandler. - */ - public void setContentHandler(ContentHandler h) { - this.handler = h; - } - -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/RootInputStream.java b/apache/org/apache/james/mime4j/RootInputStream.java deleted file mode 100644 index cc8b2411ca34fe5f238a021c02075171096aaaff..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/RootInputStream.java +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j; - -import java.io.IOException; -import java.io.InputStream; - -/** - * InputStream used by the parser to wrap the original user - * supplied stream. This stream keeps track of the current line number and - * can also be truncated. When truncated the stream will appear to have - * reached end of file. This is used by the parser's - * {@link org.apache.james.mime4j.MimeStreamParser#stop()} method. - * - * - * @version $Id: RootInputStream.java,v 1.2 2004/10/02 12:41:10 ntherning Exp $ - */ -class RootInputStream extends InputStream { - private InputStream is = null; - private int lineNumber = 1; - private int prev = -1; - private boolean truncated = false; - - /** - * Creates a new RootInputStream. - * - * @param in the stream to read from. - */ - public RootInputStream(InputStream is) { - this.is = is; - } - - /** - * Gets the current line number starting at 1 - * (the number of \r\n read so far plus 1). - * - * @return the current line number. - */ - public int getLineNumber() { - return lineNumber; - } - - /** - * Truncates this InputStream. After this call any - * call to {@link #read()}, {@link #read(byte[]) or - * {@link #read(byte[], int, int)} will return - * -1 as if end-of-file had been reached. - */ - public void truncate() { - this.truncated = true; - } - - /** - * @see java.io.InputStream#read() - */ - public int read() throws IOException { - if (truncated) { - return -1; - } - - int b = is.read(); - if (prev == '\r' && b == '\n') { - lineNumber++; - } - prev = b; - return b; - } - - /** - * - * @see java.io.InputStream#read(byte[], int, int) - */ - public int read(byte[] b, int off, int len) throws IOException { - if (truncated) { - return -1; - } - - int n = is.read(b, off, len); - for (int i = off; i < off + n; i++) { - if (prev == '\r' && b[i] == '\n') { - lineNumber++; - } - prev = b[i]; - } - return n; - } - - /** - * @see java.io.InputStream#read(byte[]) - */ - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/codec/EncoderUtil.java b/apache/org/apache/james/mime4j/codec/EncoderUtil.java deleted file mode 100644 index 6841bc9984c8327beacb6dd0888271860fad9cd1..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/codec/EncoderUtil.java +++ /dev/null @@ -1,630 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.codec; - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.BitSet; -import java.util.Locale; - -import org.apache.james.mime4j.util.CharsetUtil; - -/** - * ANDROID: THIS CLASS IS COPIED FROM A NEWER VERSION OF MIME4J - */ - -/** - * Static methods for encoding header field values. This includes encoded-words - * as defined in RFC 2047 - * or display-names of an e-mail address, for example. - * - */ -public class EncoderUtil { - - // This array is a lookup table that translates 6-bit positive integer index - // values into their "Base64 Alphabet" equivalents as specified in Table 1 - // of RFC 2045. - // ANDROID: THIS TABLE IS COPIED FROM BASE64OUTPUTSTREAM - static final byte[] BASE64_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', - 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', - 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', - 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', - '6', '7', '8', '9', '+', '/' }; - - // Byte used to pad output. - private static final byte BASE64_PAD = '='; - - private static final BitSet Q_REGULAR_CHARS = initChars("=_?"); - - private static final BitSet Q_RESTRICTED_CHARS = initChars("=_?\"#$%&'(),.:;<>@[\\]^`{|}~"); - - private static final int MAX_USED_CHARACTERS = 50; - - private static final String ENC_WORD_PREFIX = "=?"; - private static final String ENC_WORD_SUFFIX = "?="; - - private static final int ENCODED_WORD_MAX_LENGTH = 75; // RFC 2047 - - private static final BitSet TOKEN_CHARS = initChars("()<>@,;:\\\"/[]?="); - - private static final BitSet ATEXT_CHARS = initChars("()<>@.,;:\\\"[]"); - - private static BitSet initChars(String specials) { - BitSet bs = new BitSet(128); - for (char ch = 33; ch < 127; ch++) { - if (specials.indexOf(ch) == -1) { - bs.set(ch); - } - } - return bs; - } - - /** - * Selects one of the two encodings specified in RFC 2047. - */ - public enum Encoding { - /** The B encoding (identical to base64 defined in RFC 2045). */ - B, - /** The Q encoding (similar to quoted-printable defined in RFC 2045). */ - Q - } - - /** - * Indicates the intended usage of an encoded word. - */ - public enum Usage { - /** - * Encoded word is used to replace a 'text' token in any Subject or - * Comments header field. - */ - TEXT_TOKEN, - /** - * Encoded word is used to replace a 'word' entity within a 'phrase', - * for example, one that precedes an address in a From, To, or Cc - * header. - */ - WORD_ENTITY - } - - private EncoderUtil() { - } - - /** - * Encodes the display-name portion of an address. See RFC 5322 section 3.4 - * and RFC 2047 section - * 5.3. The specified string should not be folded. - * - * @param displayName - * display-name to encode. - * @return encoded display-name. - */ - public static String encodeAddressDisplayName(String displayName) { - // display-name = phrase - // phrase = 1*( encoded-word / word ) - // word = atom / quoted-string - // atom = [CFWS] 1*atext [CFWS] - // CFWS = comment or folding white space - - if (isAtomPhrase(displayName)) { - return displayName; - } else if (hasToBeEncoded(displayName, 0)) { - return encodeEncodedWord(displayName, Usage.WORD_ENTITY); - } else { - return quote(displayName); - } - } - - /** - * Encodes the local part of an address specification as described in RFC - * 5322 section 3.4.1. Leading and trailing CFWS should have been removed - * before calling this method. The specified string should not contain any - * illegal (control or non-ASCII) characters. - * - * @param localPart - * the local part to encode - * @return the encoded local part. - */ - public static String encodeAddressLocalPart(String localPart) { - // local-part = dot-atom / quoted-string - // dot-atom = [CFWS] dot-atom-text [CFWS] - // CFWS = comment or folding white space - - if (isDotAtomText(localPart)) { - return localPart; - } else { - return quote(localPart); - } - } - - /** - * Encodes the specified strings into a header parameter as described in RFC - * 2045 section 5.1 and RFC 2183 section 2. The specified strings should not - * contain any illegal (control or non-ASCII) characters. - * - * @param name - * parameter name. - * @param value - * parameter value. - * @return encoded result. - */ - public static String encodeHeaderParameter(String name, String value) { - name = name.toLowerCase(Locale.US); - - // value := token / quoted-string - if (isToken(value)) { - return name + "=" + value; - } else { - return name + "=" + quote(value); - } - } - - /** - * Shortcut method that encodes the specified text into an encoded-word if - * the text has to be encoded. - * - * @param text - * text to encode. - * @param usage - * whether the encoded-word is to be used to replace a text token - * or a word entity (see RFC 822). - * @param usedCharacters - * number of characters already used up (0 <= usedCharacters <= 50). - * @return the specified text if encoding is not necessary or an encoded - * word or a sequence of encoded words otherwise. - */ - public static String encodeIfNecessary(String text, Usage usage, - int usedCharacters) { - if (hasToBeEncoded(text, usedCharacters)) - return encodeEncodedWord(text, usage, usedCharacters); - else - return text; - } - - /** - * Determines if the specified string has to encoded into an encoded-word. - * Returns true if the text contains characters that don't - * fall into the printable ASCII character set or if the text contains a - * 'word' (sequence of non-whitespace characters) longer than 77 characters - * (including characters already used up in the line). - * - * @param text - * text to analyze. - * @param usedCharacters - * number of characters already used up (0 <= usedCharacters <= 50). - * @return true if the specified text has to be encoded into - * an encoded-word, false otherwise. - */ - public static boolean hasToBeEncoded(String text, int usedCharacters) { - if (text == null) - throw new IllegalArgumentException(); - if (usedCharacters < 0 || usedCharacters > MAX_USED_CHARACTERS) - throw new IllegalArgumentException(); - - int nonWhiteSpaceCount = usedCharacters; - - for (int idx = 0; idx < text.length(); idx++) { - char ch = text.charAt(idx); - if (ch == '\t' || ch == ' ') { - nonWhiteSpaceCount = 0; - } else { - nonWhiteSpaceCount++; - if (nonWhiteSpaceCount > 77) { - // Line cannot be folded into multiple lines with no more - // than 78 characters each. Encoding as encoded-words makes - // that possible. One character has to be reserved for - // folding white space; that leaves 77 characters. - return true; - } - - if (ch < 32 || ch >= 127) { - // non-printable ascii character has to be encoded - return true; - } - } - } - - return false; - } - - /** - * Encodes the specified text into an encoded word or a sequence of encoded - * words separated by space. The text is separated into a sequence of - * encoded words if it does not fit in a single one. - *

- * The charset to encode the specified text into a byte array and the - * encoding to use for the encoded-word are detected automatically. - *

- * This method assumes that zero characters have already been used up in the - * current line. - * - * @param text - * text to encode. - * @param usage - * whether the encoded-word is to be used to replace a text token - * or a word entity (see RFC 822). - * @return the encoded word (or sequence of encoded words if the given text - * does not fit in a single encoded word). - * @see #hasToBeEncoded(String, int) - */ - public static String encodeEncodedWord(String text, Usage usage) { - return encodeEncodedWord(text, usage, 0, null, null); - } - - /** - * Encodes the specified text into an encoded word or a sequence of encoded - * words separated by space. The text is separated into a sequence of - * encoded words if it does not fit in a single one. - *

- * The charset to encode the specified text into a byte array and the - * encoding to use for the encoded-word are detected automatically. - * - * @param text - * text to encode. - * @param usage - * whether the encoded-word is to be used to replace a text token - * or a word entity (see RFC 822). - * @param usedCharacters - * number of characters already used up (0 <= usedCharacters <= 50). - * @return the encoded word (or sequence of encoded words if the given text - * does not fit in a single encoded word). - * @see #hasToBeEncoded(String, int) - */ - public static String encodeEncodedWord(String text, Usage usage, - int usedCharacters) { - return encodeEncodedWord(text, usage, usedCharacters, null, null); - } - - /** - * Encodes the specified text into an encoded word or a sequence of encoded - * words separated by space. The text is separated into a sequence of - * encoded words if it does not fit in a single one. - * - * @param text - * text to encode. - * @param usage - * whether the encoded-word is to be used to replace a text token - * or a word entity (see RFC 822). - * @param usedCharacters - * number of characters already used up (0 <= usedCharacters <= 50). - * @param charset - * the Java charset that should be used to encode the specified - * string into a byte array. A suitable charset is detected - * automatically if this parameter is null. - * @param encoding - * the encoding to use for the encoded-word (either B or Q). A - * suitable encoding is automatically chosen if this parameter is - * null. - * @return the encoded word (or sequence of encoded words if the given text - * does not fit in a single encoded word). - * @see #hasToBeEncoded(String, int) - */ - public static String encodeEncodedWord(String text, Usage usage, - int usedCharacters, Charset charset, Encoding encoding) { - if (text == null) - throw new IllegalArgumentException(); - if (usedCharacters < 0 || usedCharacters > MAX_USED_CHARACTERS) - throw new IllegalArgumentException(); - - if (charset == null) - charset = determineCharset(text); - - String mimeCharset = CharsetUtil.toMimeCharset(charset.name()); - if (mimeCharset == null) { - // cannot happen if charset was originally null - throw new IllegalArgumentException("Unsupported charset"); - } - - byte[] bytes = encode(text, charset); - - if (encoding == null) - encoding = determineEncoding(bytes, usage); - - if (encoding == Encoding.B) { - String prefix = ENC_WORD_PREFIX + mimeCharset + "?B?"; - return encodeB(prefix, text, usedCharacters, charset, bytes); - } else { - String prefix = ENC_WORD_PREFIX + mimeCharset + "?Q?"; - return encodeQ(prefix, text, usage, usedCharacters, charset, bytes); - } - } - - /** - * Encodes the specified byte array using the B encoding defined in RFC - * 2047. - * - * @param bytes - * byte array to encode. - * @return encoded string. - */ - public static String encodeB(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - - int idx = 0; - final int end = bytes.length; - for (; idx < end - 2; idx += 3) { - int data = (bytes[idx] & 0xff) << 16 | (bytes[idx + 1] & 0xff) << 8 - | bytes[idx + 2] & 0xff; - sb.append((char) BASE64_TABLE[data >> 18 & 0x3f]); - sb.append((char) BASE64_TABLE[data >> 12 & 0x3f]); - sb.append((char) BASE64_TABLE[data >> 6 & 0x3f]); - sb.append((char) BASE64_TABLE[data & 0x3f]); - } - - if (idx == end - 2) { - int data = (bytes[idx] & 0xff) << 16 | (bytes[idx + 1] & 0xff) << 8; - sb.append((char) BASE64_TABLE[data >> 18 & 0x3f]); - sb.append((char) BASE64_TABLE[data >> 12 & 0x3f]); - sb.append((char) BASE64_TABLE[data >> 6 & 0x3f]); - sb.append((char) BASE64_PAD); - - } else if (idx == end - 1) { - int data = (bytes[idx] & 0xff) << 16; - sb.append((char) BASE64_TABLE[data >> 18 & 0x3f]); - sb.append((char) BASE64_TABLE[data >> 12 & 0x3f]); - sb.append((char) BASE64_PAD); - sb.append((char) BASE64_PAD); - } - - return sb.toString(); - } - - /** - * Encodes the specified byte array using the Q encoding defined in RFC - * 2047. - * - * @param bytes - * byte array to encode. - * @param usage - * whether the encoded-word is to be used to replace a text token - * or a word entity (see RFC 822). - * @return encoded string. - */ - public static String encodeQ(byte[] bytes, Usage usage) { - BitSet qChars = usage == Usage.TEXT_TOKEN ? Q_REGULAR_CHARS - : Q_RESTRICTED_CHARS; - - StringBuilder sb = new StringBuilder(); - - final int end = bytes.length; - for (int idx = 0; idx < end; idx++) { - int v = bytes[idx] & 0xff; - if (v == 32) { - sb.append('_'); - } else if (!qChars.get(v)) { - sb.append('='); - sb.append(hexDigit(v >>> 4)); - sb.append(hexDigit(v & 0xf)); - } else { - sb.append((char) v); - } - } - - return sb.toString(); - } - - /** - * Tests whether the specified string is a token as defined in RFC 2045 - * section 5.1. - * - * @param str - * string to test. - * @return true if the specified string is a RFC 2045 token, - * false otherwise. - */ - public static boolean isToken(String str) { - // token := 1* - // tspecials := "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "\" / - // <"> / "/" / "[" / "]" / "?" / "=" - // CTL := 0.- 31., 127. - - final int length = str.length(); - if (length == 0) - return false; - - for (int idx = 0; idx < length; idx++) { - char ch = str.charAt(idx); - if (!TOKEN_CHARS.get(ch)) - return false; - } - - return true; - } - - private static boolean isAtomPhrase(String str) { - // atom = [CFWS] 1*atext [CFWS] - - boolean containsAText = false; - - final int length = str.length(); - for (int idx = 0; idx < length; idx++) { - char ch = str.charAt(idx); - if (ATEXT_CHARS.get(ch)) { - containsAText = true; - } else if (!CharsetUtil.isWhitespace(ch)) { - return false; - } - } - - return containsAText; - } - - // RFC 5322 section 3.2.3 - private static boolean isDotAtomText(String str) { - // dot-atom-text = 1*atext *("." 1*atext) - // atext = ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / - // "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~" - - char prev = '.'; - - final int length = str.length(); - if (length == 0) - return false; - - for (int idx = 0; idx < length; idx++) { - char ch = str.charAt(idx); - - if (ch == '.') { - if (prev == '.' || idx == length - 1) - return false; - } else { - if (!ATEXT_CHARS.get(ch)) - return false; - } - - prev = ch; - } - - return true; - } - - // RFC 5322 section 3.2.4 - private static String quote(String str) { - // quoted-string = [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS] - // qcontent = qtext / quoted-pair - // qtext = %d33 / %d35-91 / %d93-126 - // quoted-pair = ("\" (VCHAR / WSP)) - // VCHAR = %x21-7E - // DQUOTE = %x22 - - String escaped = str.replaceAll("[\\\\\"]", "\\\\$0"); - return "\"" + escaped + "\""; - } - - private static String encodeB(String prefix, String text, - int usedCharacters, Charset charset, byte[] bytes) { - int encodedLength = bEncodedLength(bytes); - - int totalLength = prefix.length() + encodedLength - + ENC_WORD_SUFFIX.length(); - if (totalLength <= ENCODED_WORD_MAX_LENGTH - usedCharacters) { - return prefix + encodeB(bytes) + ENC_WORD_SUFFIX; - } else { - int splitOffset = text.offsetByCodePoints(text.length() / 2, -1); - - String part1 = text.substring(0, splitOffset); - byte[] bytes1 = encode(part1, charset); - String word1 = encodeB(prefix, part1, usedCharacters, charset, - bytes1); - - String part2 = text.substring(splitOffset); - byte[] bytes2 = encode(part2, charset); - String word2 = encodeB(prefix, part2, 0, charset, bytes2); - - return word1 + " " + word2; - } - } - - private static int bEncodedLength(byte[] bytes) { - return (bytes.length + 2) / 3 * 4; - } - - private static String encodeQ(String prefix, String text, Usage usage, - int usedCharacters, Charset charset, byte[] bytes) { - int encodedLength = qEncodedLength(bytes, usage); - - int totalLength = prefix.length() + encodedLength - + ENC_WORD_SUFFIX.length(); - if (totalLength <= ENCODED_WORD_MAX_LENGTH - usedCharacters) { - return prefix + encodeQ(bytes, usage) + ENC_WORD_SUFFIX; - } else { - int splitOffset = text.offsetByCodePoints(text.length() / 2, -1); - - String part1 = text.substring(0, splitOffset); - byte[] bytes1 = encode(part1, charset); - String word1 = encodeQ(prefix, part1, usage, usedCharacters, - charset, bytes1); - - String part2 = text.substring(splitOffset); - byte[] bytes2 = encode(part2, charset); - String word2 = encodeQ(prefix, part2, usage, 0, charset, bytes2); - - return word1 + " " + word2; - } - } - - private static int qEncodedLength(byte[] bytes, Usage usage) { - BitSet qChars = usage == Usage.TEXT_TOKEN ? Q_REGULAR_CHARS - : Q_RESTRICTED_CHARS; - - int count = 0; - - for (int idx = 0; idx < bytes.length; idx++) { - int v = bytes[idx] & 0xff; - if (v == 32) { - count++; - } else if (!qChars.get(v)) { - count += 3; - } else { - count++; - } - } - - return count; - } - - private static byte[] encode(String text, Charset charset) { - ByteBuffer buffer = charset.encode(text); - byte[] bytes = new byte[buffer.limit()]; - buffer.get(bytes); - return bytes; - } - - private static Charset determineCharset(String text) { - // it is an important property of iso-8859-1 that it directly maps - // unicode code points 0000 to 00ff to byte values 00 to ff. - boolean ascii = true; - final int len = text.length(); - for (int index = 0; index < len; index++) { - char ch = text.charAt(index); - if (ch > 0xff) { - return CharsetUtil.UTF_8; - } - if (ch > 0x7f) { - ascii = false; - } - } - return ascii ? CharsetUtil.US_ASCII : CharsetUtil.ISO_8859_1; - } - - private static Encoding determineEncoding(byte[] bytes, Usage usage) { - if (bytes.length == 0) - return Encoding.Q; - - BitSet qChars = usage == Usage.TEXT_TOKEN ? Q_REGULAR_CHARS - : Q_RESTRICTED_CHARS; - - int qEncoded = 0; - for (int i = 0; i < bytes.length; i++) { - int v = bytes[i] & 0xff; - if (v != 32 && !qChars.get(v)) { - qEncoded++; - } - } - - int percentage = qEncoded * 100 / bytes.length; - return percentage > 30 ? Encoding.B : Encoding.Q; - } - - private static char hexDigit(int i) { - return i < 10 ? (char) (i + '0') : (char) (i - 10 + 'A'); - } -} diff --git a/apache/org/apache/james/mime4j/decoder/Base64InputStream.java b/apache/org/apache/james/mime4j/decoder/Base64InputStream.java deleted file mode 100644 index 77f5d7d4ac1c08c3c5792c46929b53cc4932af94..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/decoder/Base64InputStream.java +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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. * - ****************************************************************/ - -/** - * Modified to improve efficiency by Android 21-Aug-2009 - */ - -package org.apache.james.mime4j.decoder; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Performs Base-64 decoding on an underlying stream. - * - * - * @version $Id: Base64InputStream.java,v 1.3 2004/11/29 13:15:47 ntherning Exp $ - */ -public class Base64InputStream extends InputStream { - private final InputStream s; - private int outCount = 0; - private int outIndex = 0; - private final int[] outputBuffer = new int[3]; - private final byte[] inputBuffer = new byte[4]; - private boolean done = false; - - public Base64InputStream(InputStream s) { - this.s = s; - } - - /** - * Closes the underlying stream. - * - * @throws IOException on I/O errors. - */ - @Override - public void close() throws IOException { - s.close(); - } - - @Override - public int read() throws IOException { - if (outIndex == outCount) { - fillBuffer(); - if (outIndex == outCount) { - return -1; - } - } - - return outputBuffer[outIndex++]; - } - - /** - * Retrieve data from the underlying stream, decode it, - * and put the results in the byteq. - * @throws IOException - */ - private void fillBuffer() throws IOException { - outCount = 0; - outIndex = 0; - int inCount = 0; - - int i; - // "done" is needed for the two successive '=' at the end - while (!done) { - switch (i = s.read()) { - case -1: - // No more input - just return, let outputBuffer drain out, and be done - return; - case '=': - // once we meet the first '=', avoid reading the second '=' - done = true; - decodeAndEnqueue(inCount); - return; - default: - byte sX = TRANSLATION[i]; - if (sX < 0) continue; - inputBuffer[inCount++] = sX; - if (inCount == 4) { - decodeAndEnqueue(inCount); - return; - } - break; - } - } - } - - private void decodeAndEnqueue(int len) { - int accum = 0; - accum |= inputBuffer[0] << 18; - accum |= inputBuffer[1] << 12; - accum |= inputBuffer[2] << 6; - accum |= inputBuffer[3]; - - // There's a bit of duplicated code here because we want to have straight-through operation - // for the most common case of len==4 - if (len == 4) { - outputBuffer[0] = (accum >> 16) & 0xFF; - outputBuffer[1] = (accum >> 8) & 0xFF; - outputBuffer[2] = (accum) & 0xFF; - outCount = 3; - return; - } else if (len == 3) { - outputBuffer[0] = (accum >> 16) & 0xFF; - outputBuffer[1] = (accum >> 8) & 0xFF; - outCount = 2; - return; - } else { // len == 2 - outputBuffer[0] = (accum >> 16) & 0xFF; - outCount = 1; - return; - } - } - - private static byte[] TRANSLATION = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */ - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */ - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */ - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xA0 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xB0 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xC0 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xD0 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xF0 */ - }; - - -} diff --git a/apache/org/apache/james/mime4j/decoder/ByteQueue.java b/apache/org/apache/james/mime4j/decoder/ByteQueue.java deleted file mode 100644 index 6d7ccef5243725a87cd66591568847570f279b76..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/decoder/ByteQueue.java +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.decoder; - -import java.util.Iterator; - -public class ByteQueue { - - private UnboundedFifoByteBuffer buf; - private int initialCapacity = -1; - - public ByteQueue() { - buf = new UnboundedFifoByteBuffer(); - } - - public ByteQueue(int initialCapacity) { - buf = new UnboundedFifoByteBuffer(initialCapacity); - this.initialCapacity = initialCapacity; - } - - public void enqueue(byte b) { - buf.add(b); - } - - public byte dequeue() { - return buf.remove(); - } - - public int count() { - return buf.size(); - } - - public void clear() { - if (initialCapacity != -1) - buf = new UnboundedFifoByteBuffer(initialCapacity); - else - buf = new UnboundedFifoByteBuffer(); - } - - public Iterator iterator() { - return buf.iterator(); - } - - -} diff --git a/apache/org/apache/james/mime4j/decoder/DecoderUtil.java b/apache/org/apache/james/mime4j/decoder/DecoderUtil.java deleted file mode 100644 index 48fe07dee57257fab36b8e6d0248669857275d5f..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/decoder/DecoderUtil.java +++ /dev/null @@ -1,284 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.decoder; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed -import org.apache.james.mime4j.util.CharsetUtil; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -/** - * Static methods for decoding strings, byte arrays and encoded words. - * - * - * @version $Id: DecoderUtil.java,v 1.3 2005/02/07 15:33:59 ntherning Exp $ - */ -public class DecoderUtil { - private static Log log = LogFactory.getLog(DecoderUtil.class); - - /** - * Decodes a string containing quoted-printable encoded data. - * - * @param s the string to decode. - * @return the decoded bytes. - */ - public static byte[] decodeBaseQuotedPrintable(String s) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - try { - byte[] bytes = s.getBytes("US-ASCII"); - - QuotedPrintableInputStream is = new QuotedPrintableInputStream( - new ByteArrayInputStream(bytes)); - - int b = 0; - while ((b = is.read()) != -1) { - baos.write(b); - } - } catch (IOException e) { - /* - * This should never happen! - */ - log.error(e); - } - - return baos.toByteArray(); - } - - /** - * Decodes a string containing base64 encoded data. - * - * @param s the string to decode. - * @return the decoded bytes. - */ - public static byte[] decodeBase64(String s) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - try { - byte[] bytes = s.getBytes("US-ASCII"); - - Base64InputStream is = new Base64InputStream( - new ByteArrayInputStream(bytes)); - - int b = 0; - while ((b = is.read()) != -1) { - baos.write(b); - } - } catch (IOException e) { - /* - * This should never happen! - */ - log.error(e); - } - - return baos.toByteArray(); - } - - /** - * Decodes an encoded word encoded with the 'B' encoding (described in - * RFC 2047) found in a header field body. - * - * @param encodedWord the encoded word to decode. - * @param charset the Java charset to use. - * @return the decoded string. - * @throws UnsupportedEncodingException if the given Java charset isn't - * supported. - */ - public static String decodeB(String encodedWord, String charset) - throws UnsupportedEncodingException { - - return new String(decodeBase64(encodedWord), charset); - } - - /** - * Decodes an encoded word encoded with the 'Q' encoding (described in - * RFC 2047) found in a header field body. - * - * @param encodedWord the encoded word to decode. - * @param charset the Java charset to use. - * @return the decoded string. - * @throws UnsupportedEncodingException if the given Java charset isn't - * supported. - */ - public static String decodeQ(String encodedWord, String charset) - throws UnsupportedEncodingException { - - /* - * Replace _ with =20 - */ - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < encodedWord.length(); i++) { - char c = encodedWord.charAt(i); - if (c == '_') { - sb.append("=20"); - } else { - sb.append(c); - } - } - - return new String(decodeBaseQuotedPrintable(sb.toString()), charset); - } - - /** - * Decodes a string containing encoded words as defined by RFC 2047. - * Encoded words in have the form - * =?charset?enc?Encoded word?= where enc is either 'Q' or 'q' for - * quoted-printable and 'B' or 'b' for Base64. - * - * ANDROID: COPIED FROM A NEWER VERSION OF MIME4J - * - * @param body the string to decode. - * @return the decoded string. - */ - public static String decodeEncodedWords(String body) { - - // ANDROID: Most strings will not include "=?" so a quick test can prevent unneeded - // object creation. This could also be handled via lazy creation of the StringBuilder. - if (body.indexOf("=?") == -1) { - return body; - } - - int previousEnd = 0; - boolean previousWasEncoded = false; - - StringBuilder sb = new StringBuilder(); - - while (true) { - int begin = body.indexOf("=?", previousEnd); - - // ANDROID: The mime4j original version has an error here. It gets confused if - // the encoded string begins with an '=' (just after "?Q?"). This patch seeks forward - // to find the two '?' in the "header", before looking for the final "?=". - if (begin == -1) { - break; - } - int qm1 = body.indexOf('?', begin + 2); - if (qm1 == -1) { - break; - } - int qm2 = body.indexOf('?', qm1 + 1); - if (qm2 == -1) { - break; - } - int end = body.indexOf("?=", qm2 + 1); - if (end == -1) { - break; - } - end += 2; - - String sep = body.substring(previousEnd, begin); - - String decoded = decodeEncodedWord(body, begin, end); - if (decoded == null) { - sb.append(sep); - sb.append(body.substring(begin, end)); - } else { - if (!previousWasEncoded || !CharsetUtil.isWhitespace(sep)) { - sb.append(sep); - } - sb.append(decoded); - } - - previousEnd = end; - previousWasEncoded = decoded != null; - } - - if (previousEnd == 0) - return body; - - sb.append(body.substring(previousEnd)); - return sb.toString(); - } - - // return null on error. Begin is index of '=?' in body. - public static String decodeEncodedWord(String body, int begin, int end) { - // Skip the '?=' chars in body and scan forward from there for next '?' - int qm1 = body.indexOf('?', begin + 2); - if (qm1 == -1 || qm1 == end - 2) - return null; - - int qm2 = body.indexOf('?', qm1 + 1); - if (qm2 == -1 || qm2 == end - 2) - return null; - - String mimeCharset = body.substring(begin + 2, qm1); - String encoding = body.substring(qm1 + 1, qm2); - String encodedText = body.substring(qm2 + 1, end - 2); - - String charset = CharsetUtil.toJavaCharset(mimeCharset); - if (charset == null) { - if (log.isWarnEnabled()) { - log.warn("MIME charset '" + mimeCharset + "' in encoded word '" - + body.substring(begin, end) + "' doesn't have a " - + "corresponding Java charset"); - } - return null; - } else if (!CharsetUtil.isDecodingSupported(charset)) { - if (log.isWarnEnabled()) { - log.warn("Current JDK doesn't support decoding of charset '" - + charset + "' (MIME charset '" + mimeCharset - + "' in encoded word '" + body.substring(begin, end) - + "')"); - } - return null; - } - - if (encodedText.length() == 0) { - if (log.isWarnEnabled()) { - log.warn("Missing encoded text in encoded word: '" - + body.substring(begin, end) + "'"); - } - return null; - } - - try { - if (encoding.equalsIgnoreCase("Q")) { - return DecoderUtil.decodeQ(encodedText, charset); - } else if (encoding.equalsIgnoreCase("B")) { - return DecoderUtil.decodeB(encodedText, charset); - } else { - if (log.isWarnEnabled()) { - log.warn("Warning: Unknown encoding in encoded word '" - + body.substring(begin, end) + "'"); - } - return null; - } - } catch (UnsupportedEncodingException e) { - // should not happen because of isDecodingSupported check above - if (log.isWarnEnabled()) { - log.warn("Unsupported encoding in encoded word '" - + body.substring(begin, end) + "'", e); - } - return null; - } catch (RuntimeException e) { - if (log.isWarnEnabled()) { - log.warn("Could not decode encoded word '" - + body.substring(begin, end) + "'", e); - } - return null; - } - } -} diff --git a/apache/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java b/apache/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java deleted file mode 100644 index e43f398f92e0a491e2ff40e4c331177314dab3b8..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/decoder/QuotedPrintableInputStream.java +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.decoder; - -import java.io.IOException; -import java.io.InputStream; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed - -/** - * Performs Quoted-Printable decoding on an underlying stream. - * - * - * - * @version $Id: QuotedPrintableInputStream.java,v 1.3 2004/11/29 13:15:47 ntherning Exp $ - */ -public class QuotedPrintableInputStream extends InputStream { - private static Log log = LogFactory.getLog(QuotedPrintableInputStream.class); - - private InputStream stream; - ByteQueue byteq = new ByteQueue(); - ByteQueue pushbackq = new ByteQueue(); - private byte state = 0; - - public QuotedPrintableInputStream(InputStream stream) { - this.stream = stream; - } - - /** - * Closes the underlying stream. - * - * @throws IOException on I/O errors. - */ - public void close() throws IOException { - stream.close(); - } - - public int read() throws IOException { - fillBuffer(); - if (byteq.count() == 0) - return -1; - else { - byte val = byteq.dequeue(); - if (val >= 0) - return val; - else - return val & 0xFF; - } - } - - /** - * Pulls bytes out of the underlying stream and places them in the - * pushback queue. This is necessary (vs. reading from the - * underlying stream directly) to detect and filter out "transport - * padding" whitespace, i.e., all whitespace that appears immediately - * before a CRLF. - * - * @throws IOException Underlying stream threw IOException. - */ - private void populatePushbackQueue() throws IOException { - //Debug.verify(pushbackq.count() == 0, "PopulatePushbackQueue called when pushback queue was not empty!"); - - if (pushbackq.count() != 0) - return; - - while (true) { - int i = stream.read(); - switch (i) { - case -1: - // stream is done - pushbackq.clear(); // discard any whitespace preceding EOF - return; - case ' ': - case '\t': - pushbackq.enqueue((byte)i); - break; - case '\r': - case '\n': - pushbackq.clear(); // discard any whitespace preceding EOL - pushbackq.enqueue((byte)i); - return; - default: - pushbackq.enqueue((byte)i); - return; - } - } - } - - /** - * Causes the pushback queue to get populated if it is empty, then - * consumes and decodes bytes out of it until one or more bytes are - * in the byte queue. This decoding step performs the actual QP - * decoding. - * - * @throws IOException Underlying stream threw IOException. - */ - private void fillBuffer() throws IOException { - byte msdChar = 0; // first digit of escaped num - while (byteq.count() == 0) { - if (pushbackq.count() == 0) { - populatePushbackQueue(); - if (pushbackq.count() == 0) - return; - } - - byte b = (byte)pushbackq.dequeue(); - - switch (state) { - case 0: // start state, no bytes pending - if (b != '=') { - byteq.enqueue(b); - break; // state remains 0 - } else { - state = 1; - break; - } - case 1: // encountered "=" so far - if (b == '\r') { - state = 2; - break; - } else if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) { - state = 3; - msdChar = b; // save until next digit encountered - break; - } else if (b == '=') { - /* - * Special case when == is encountered. - * Emit one = and stay in this state. - */ - if (log.isWarnEnabled()) { - log.warn("Malformed MIME; got =="); - } - byteq.enqueue((byte)'='); - break; - } else { - if (log.isWarnEnabled()) { - log.warn("Malformed MIME; expected \\r or " - + "[0-9A-Z], got " + b); - } - state = 0; - byteq.enqueue((byte)'='); - byteq.enqueue(b); - break; - } - case 2: // encountered "=\r" so far - if (b == '\n') { - state = 0; - break; - } else { - if (log.isWarnEnabled()) { - log.warn("Malformed MIME; expected " - + (int)'\n' + ", got " + b); - } - state = 0; - byteq.enqueue((byte)'='); - byteq.enqueue((byte)'\r'); - byteq.enqueue(b); - break; - } - case 3: // encountered = so far; expecting another to complete the octet - if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) { - byte msd = asciiCharToNumericValue(msdChar); - byte low = asciiCharToNumericValue(b); - state = 0; - byteq.enqueue((byte)((msd << 4) | low)); - break; - } else { - if (log.isWarnEnabled()) { - log.warn("Malformed MIME; expected " - + "[0-9A-Z], got " + b); - } - state = 0; - byteq.enqueue((byte)'='); - byteq.enqueue(msdChar); - byteq.enqueue(b); - break; - } - default: // should never happen - log.error("Illegal state: " + state); - state = 0; - byteq.enqueue(b); - break; - } - } - } - - /** - * Converts '0' => 0, 'A' => 10, etc. - * @param c ASCII character value. - * @return Numeric value of hexadecimal character. - */ - private byte asciiCharToNumericValue(byte c) { - if (c >= '0' && c <= '9') { - return (byte)(c - '0'); - } else if (c >= 'A' && c <= 'Z') { - return (byte)(0xA + (c - 'A')); - } else if (c >= 'a' && c <= 'z') { - return (byte)(0xA + (c - 'a')); - } else { - /* - * This should never happen since all calls to this method - * are preceded by a check that c is in [0-9A-Za-z] - */ - throw new IllegalArgumentException((char) c - + " is not a hexadecimal digit"); - } - } - -} diff --git a/apache/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java b/apache/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java deleted file mode 100644 index f01194fd10b668130a3b1015838d0a172fcdd36f..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/decoder/UnboundedFifoByteBuffer.java +++ /dev/null @@ -1,272 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.decoder; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * UnboundedFifoByteBuffer is a very efficient buffer implementation. - * According to performance testing, it exhibits a constant access time, but it - * also outperforms ArrayList when used for the same purpose. - *

- * The removal order of an UnboundedFifoByteBuffer is based on the insertion - * order; elements are removed in the same order in which they were added. - * The iteration order is the same as the removal order. - *

- * The {@link #remove()} and {@link #get()} operations perform in constant time. - * The {@link #add(Object)} operation performs in amortized constant time. All - * other operations perform in linear time or worse. - *

- * Note that this implementation is not synchronized. The following can be - * used to provide synchronized access to your UnboundedFifoByteBuffer: - *

- *   Buffer fifo = BufferUtils.synchronizedBuffer(new UnboundedFifoByteBuffer());
- * 
- *

- * This buffer prevents null objects from being added. - * - * @since Commons Collections 3.0 (previously in main package v2.1) - * @version $Revision: 1.1 $ $Date: 2004/08/24 06:52:02 $ - * - * - * - * - * - * - */ -class UnboundedFifoByteBuffer { - - protected byte[] buffer; - protected int head; - protected int tail; - - /** - * Constructs an UnboundedFifoByteBuffer with the default number of elements. - * It is exactly the same as performing the following: - * - *

-     *   new UnboundedFifoByteBuffer(32);
-     * 
- */ - public UnboundedFifoByteBuffer() { - this(32); - } - - /** - * Constructs an UnboundedFifoByteBuffer with the specified number of elements. - * The integer must be a positive integer. - * - * @param initialSize the initial size of the buffer - * @throws IllegalArgumentException if the size is less than 1 - */ - public UnboundedFifoByteBuffer(int initialSize) { - if (initialSize <= 0) { - throw new IllegalArgumentException("The size must be greater than 0"); - } - buffer = new byte[initialSize + 1]; - head = 0; - tail = 0; - } - - /** - * Returns the number of elements stored in the buffer. - * - * @return this buffer's size - */ - public int size() { - int size = 0; - - if (tail < head) { - size = buffer.length - head + tail; - } else { - size = tail - head; - } - - return size; - } - - /** - * Returns true if this buffer is empty; false otherwise. - * - * @return true if this buffer is empty - */ - public boolean isEmpty() { - return (size() == 0); - } - - /** - * Adds the given element to this buffer. - * - * @param b the byte to add - * @return true, always - */ - public boolean add(final byte b) { - - if (size() + 1 >= buffer.length) { - byte[] tmp = new byte[((buffer.length - 1) * 2) + 1]; - - int j = 0; - for (int i = head; i != tail;) { - tmp[j] = buffer[i]; - buffer[i] = 0; - - j++; - i++; - if (i == buffer.length) { - i = 0; - } - } - - buffer = tmp; - head = 0; - tail = j; - } - - buffer[tail] = b; - tail++; - if (tail >= buffer.length) { - tail = 0; - } - return true; - } - - /** - * Returns the next object in the buffer. - * - * @return the next object in the buffer - * @throws BufferUnderflowException if this buffer is empty - */ - public byte get() { - if (isEmpty()) { - throw new IllegalStateException("The buffer is already empty"); - } - - return buffer[head]; - } - - /** - * Removes the next object from the buffer - * - * @return the removed object - * @throws BufferUnderflowException if this buffer is empty - */ - public byte remove() { - if (isEmpty()) { - throw new IllegalStateException("The buffer is already empty"); - } - - byte element = buffer[head]; - - head++; - if (head >= buffer.length) { - head = 0; - } - - return element; - } - - /** - * Increments the internal index. - * - * @param index the index to increment - * @return the updated index - */ - private int increment(int index) { - index++; - if (index >= buffer.length) { - index = 0; - } - return index; - } - - /** - * Decrements the internal index. - * - * @param index the index to decrement - * @return the updated index - */ - private int decrement(int index) { - index--; - if (index < 0) { - index = buffer.length - 1; - } - return index; - } - - /** - * Returns an iterator over this buffer's elements. - * - * @return an iterator over this buffer's elements - */ - public Iterator iterator() { - return new Iterator() { - - private int index = head; - private int lastReturnedIndex = -1; - - public boolean hasNext() { - return index != tail; - - } - - public Object next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - lastReturnedIndex = index; - index = increment(index); - return new Byte(buffer[lastReturnedIndex]); - } - - public void remove() { - if (lastReturnedIndex == -1) { - throw new IllegalStateException(); - } - - // First element can be removed quickly - if (lastReturnedIndex == head) { - UnboundedFifoByteBuffer.this.remove(); - lastReturnedIndex = -1; - return; - } - - // Other elements require us to shift the subsequent elements - int i = lastReturnedIndex + 1; - while (i != tail) { - if (i >= buffer.length) { - buffer[i - 1] = buffer[0]; - i = 0; - } else { - buffer[i - 1] = buffer[i]; - i++; - } - } - - lastReturnedIndex = -1; - tail = decrement(tail); - buffer[tail] = 0; - index = decrement(index); - } - - }; - } - -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/field/AddressListField.java b/apache/org/apache/james/mime4j/field/AddressListField.java deleted file mode 100644 index df9f3983562a0f2e93a0d0e855b035470d545c7f..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/AddressListField.java +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed -import org.apache.james.mime4j.field.address.AddressList; -import org.apache.james.mime4j.field.address.parser.ParseException; - -public class AddressListField extends Field { - private AddressList addressList; - private ParseException parseException; - - protected AddressListField(String name, String body, String raw, AddressList addressList, ParseException parseException) { - super(name, body, raw); - this.addressList = addressList; - this.parseException = parseException; - } - - public AddressList getAddressList() { - return addressList; - } - - public ParseException getParseException() { - return parseException; - } - - public static class Parser implements FieldParser { - private static Log log = LogFactory.getLog(Parser.class); - - public Field parse(final String name, final String body, final String raw) { - AddressList addressList = null; - ParseException parseException = null; - try { - addressList = AddressList.parse(body); - } - catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug("Parsing value '" + body + "': "+ e.getMessage()); - } - parseException = e; - } - return new AddressListField(name, body, raw, addressList, parseException); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/ContentTransferEncodingField.java b/apache/org/apache/james/mime4j/field/ContentTransferEncodingField.java deleted file mode 100644 index 73d8d233921b3f8d61dee4f592960c98dd881b8b..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/ContentTransferEncodingField.java +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - - - -/** - * Represents a Content-Transfer-Encoding field. - * - * - * @version $Id: ContentTransferEncodingField.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $ - */ -public class ContentTransferEncodingField extends Field { - /** - * The 7bit encoding. - */ - public static final String ENC_7BIT = "7bit"; - /** - * The 8bit encoding. - */ - public static final String ENC_8BIT = "8bit"; - /** - * The binary encoding. - */ - public static final String ENC_BINARY = "binary"; - /** - * The quoted-printable encoding. - */ - public static final String ENC_QUOTED_PRINTABLE = "quoted-printable"; - /** - * The base64 encoding. - */ - public static final String ENC_BASE64 = "base64"; - - private String encoding; - - protected ContentTransferEncodingField(String name, String body, String raw, String encoding) { - super(name, body, raw); - this.encoding = encoding; - } - - /** - * Gets the encoding defined in this field. - * - * @return the encoding or an empty string if not set. - */ - public String getEncoding() { - return encoding; - } - - /** - * Gets the encoding of the given field if. Returns the default - * 7bit if not set or if - * f is null. - * - * @return the encoding. - */ - public static String getEncoding(ContentTransferEncodingField f) { - if (f != null && f.getEncoding().length() != 0) { - return f.getEncoding(); - } - return ENC_7BIT; - } - - public static class Parser implements FieldParser { - public Field parse(final String name, final String body, final String raw) { - final String encoding = body.trim().toLowerCase(); - return new ContentTransferEncodingField(name, body, raw, encoding); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/ContentTypeField.java b/apache/org/apache/james/mime4j/field/ContentTypeField.java deleted file mode 100644 index ad9f7f9ac4db5c75fbb5f195917f51d44d836ae3..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/ContentTypeField.java +++ /dev/null @@ -1,259 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed -import org.apache.james.mime4j.field.contenttype.parser.ContentTypeParser; -import org.apache.james.mime4j.field.contenttype.parser.ParseException; -import org.apache.james.mime4j.field.contenttype.parser.TokenMgrError; - -/** - * Represents a Content-Type field. - * - *

TODO: Remove dependency on Java 1.4 regexps

- * - * - * @version $Id: ContentTypeField.java,v 1.6 2005/01/27 14:16:31 ntherning Exp $ - */ -public class ContentTypeField extends Field { - - /** - * The prefix of all multipart MIME types. - */ - public static final String TYPE_MULTIPART_PREFIX = "multipart/"; - /** - * The multipart/digest MIME type. - */ - public static final String TYPE_MULTIPART_DIGEST = "multipart/digest"; - /** - * The text/plain MIME type. - */ - public static final String TYPE_TEXT_PLAIN = "text/plain"; - /** - * The message/rfc822 MIME type. - */ - public static final String TYPE_MESSAGE_RFC822 = "message/rfc822"; - /** - * The name of the boundary parameter. - */ - public static final String PARAM_BOUNDARY = "boundary"; - /** - * The name of the charset parameter. - */ - public static final String PARAM_CHARSET = "charset"; - - private String mimeType = ""; - private Map parameters = null; - private ParseException parseException; - - protected ContentTypeField(String name, String body, String raw, String mimeType, Map parameters, ParseException parseException) { - super(name, body, raw); - this.mimeType = mimeType; - this.parameters = parameters; - this.parseException = parseException; - } - - /** - * Gets the exception that was raised during parsing of - * the field value, if any; otherwise, null. - */ - public ParseException getParseException() { - return parseException; - } - - /** - * Gets the MIME type defined in this Content-Type field. - * - * @return the MIME type or an empty string if not set. - */ - public String getMimeType() { - return mimeType; - } - - /** - * Gets the MIME type defined in the child's - * Content-Type field or derives a MIME type from the parent - * if child is null or hasn't got a MIME type value set. - * If child's MIME type is multipart but no boundary - * has been set the MIME type of child will be derived from - * the parent. - * - * @param child the child. - * @param parent the parent. - * @return the MIME type. - */ - public static String getMimeType(ContentTypeField child, - ContentTypeField parent) { - - if (child == null || child.getMimeType().length() == 0 - || child.isMultipart() && child.getBoundary() == null) { - - if (parent != null && parent.isMimeType(TYPE_MULTIPART_DIGEST)) { - return TYPE_MESSAGE_RFC822; - } else { - return TYPE_TEXT_PLAIN; - } - } - - return child.getMimeType(); - } - - /** - * Gets the value of a parameter. Parameter names are case-insensitive. - * - * @param name the name of the parameter to get. - * @return the parameter value or null if not set. - */ - public String getParameter(String name) { - return parameters != null - ? parameters.get(name.toLowerCase()) - : null; - } - - /** - * Gets all parameters. - * - * @return the parameters. - */ - public Map getParameters() { - if (parameters != null) { - return Collections.unmodifiableMap(parameters); - } - return Collections.emptyMap(); - } - - /** - * Gets the value of the boundary parameter if set. - * - * @return the boundary parameter value or null - * if not set. - */ - public String getBoundary() { - return getParameter(PARAM_BOUNDARY); - } - - /** - * Gets the value of the charset parameter if set. - * - * @return the charset parameter value or null - * if not set. - */ - public String getCharset() { - return getParameter(PARAM_CHARSET); - } - - /** - * Gets the value of the charset parameter if set for the - * given field. Returns the default us-ascii if not set or if - * f is null. - * - * @return the charset parameter value. - */ - public static String getCharset(ContentTypeField f) { - if (f != null) { - if (f.getCharset() != null && f.getCharset().length() > 0) { - return f.getCharset(); - } - } - return "us-ascii"; - } - - /** - * Determines if the MIME type of this field matches the given one. - * - * @param mimeType the MIME type to match against. - * @return true if the MIME type of this field matches, - * false otherwise. - */ - public boolean isMimeType(String mimeType) { - return this.mimeType.equalsIgnoreCase(mimeType); - } - - /** - * Determines if the MIME type of this field is multipart/*. - * - * @return true if this field is has a multipart/* - * MIME type, false otherwise. - */ - public boolean isMultipart() { - return mimeType.startsWith(TYPE_MULTIPART_PREFIX); - } - - public static class Parser implements FieldParser { - private static Log log = LogFactory.getLog(Parser.class); - - public Field parse(final String name, final String body, final String raw) { - ParseException parseException = null; - String mimeType = ""; - Map parameters = null; - - ContentTypeParser parser = new ContentTypeParser(new StringReader(body)); - try { - parser.parseAll(); - } - catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug("Parsing value '" + body + "': "+ e.getMessage()); - } - parseException = e; - } - catch (TokenMgrError e) { - if (log.isDebugEnabled()) { - log.debug("Parsing value '" + body + "': "+ e.getMessage()); - } - parseException = new ParseException(e.getMessage()); - } - - try { - final String type = parser.getType(); - final String subType = parser.getSubType(); - - if (type != null && subType != null) { - mimeType = (type + "/" + parser.getSubType()).toLowerCase(); - - ArrayList paramNames = parser.getParamNames(); - ArrayList paramValues = parser.getParamValues(); - - if (paramNames != null && paramValues != null) { - for (int i = 0; i < paramNames.size() && i < paramValues.size(); i++) { - if (parameters == null) - parameters = new HashMap((int)(paramNames.size() * 1.3 + 1)); - String paramName = paramNames.get(i).toLowerCase(); - String paramValue = paramValues.get(i); - parameters.put(paramName, paramValue); - } - } - } - } - catch (NullPointerException npe) { - } - return new ContentTypeField(name, body, raw, mimeType, parameters, parseException); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/DateTimeField.java b/apache/org/apache/james/mime4j/field/DateTimeField.java deleted file mode 100644 index 2336d99db0051aaafd58c5af323cc26dbcf64600..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/DateTimeField.java +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -//BEGIN android-changed: Stubbing out logging - -import android.text.TextUtils; -import java.util.regex.Pattern; -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; - -//END -import org.apache.james.mime4j.field.datetime.DateTime; -import org.apache.james.mime4j.field.datetime.parser.ParseException; - -import java.util.Date; - -public class DateTimeField extends Field { - private Date date; - private ParseException parseException; - - //BEGIN android-changed - // "GMT" + "+" or "-" + 4 digits - private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE = - Pattern.compile("GMT([-+]\\d{4})$"); - //END android-changed - - protected DateTimeField(String name, String body, String raw, Date date, ParseException parseException) { - super(name, body, raw); - this.date = date; - this.parseException = parseException; - } - - public Date getDate() { - return date; - } - - public ParseException getParseException() { - return parseException; - } - - public static class Parser implements FieldParser { - private static Log log = LogFactory.getLog(Parser.class); - - public Field parse(final String name, String body, final String raw) { - Date date = null; - ParseException parseException = null; - //BEGIN android-changed - body = cleanUpMimeDate(body); - //END android-changed - try { - date = DateTime.parse(body).getDate(); - } - catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug("Parsing value '" + body + "': "+ e.getMessage()); - } - parseException = e; - } - return new DateTimeField(name, body, raw, date, parseException); - } - } - - //BEGIN android-changed - /** - * Try to make a date MIME(RFC 2822/5322)-compliant. - * - *

It fixes: - "Thu, 10 Dec 09 15:08:08 GMT-0700" to "Thu, 10 Dec 09 15:08:08 -0700" (4 digit - * zone value can't be preceded by "GMT") We got a report saying eBay sends a date in this format - */ - private static String cleanUpMimeDate(String date) { - if (TextUtils.isEmpty(date)) { - return date; - } - date = DATE_CLEANUP_PATTERN_WRONG_TIMEZONE.matcher(date).replaceFirst("$1"); - return date; - } - //END android-changed -} diff --git a/apache/org/apache/james/mime4j/field/DefaultFieldParser.java b/apache/org/apache/james/mime4j/field/DefaultFieldParser.java deleted file mode 100644 index 3695afe3e183afaf07f6dbbaec496adc0e445365..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/DefaultFieldParser.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2006 the mime4j 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 org.apache.james.mime4j.field; - -public class DefaultFieldParser extends DelegatingFieldParser { - - public DefaultFieldParser() { - setFieldParser(Field.CONTENT_TRANSFER_ENCODING, new ContentTransferEncodingField.Parser()); - setFieldParser(Field.CONTENT_TYPE, new ContentTypeField.Parser()); - - final DateTimeField.Parser dateTimeParser = new DateTimeField.Parser(); - setFieldParser(Field.DATE, dateTimeParser); - setFieldParser(Field.RESENT_DATE, dateTimeParser); - - final MailboxListField.Parser mailboxListParser = new MailboxListField.Parser(); - setFieldParser(Field.FROM, mailboxListParser); - setFieldParser(Field.RESENT_FROM, mailboxListParser); - - final MailboxField.Parser mailboxParser = new MailboxField.Parser(); - setFieldParser(Field.SENDER, mailboxParser); - setFieldParser(Field.RESENT_SENDER, mailboxParser); - - final AddressListField.Parser addressListParser = new AddressListField.Parser(); - setFieldParser(Field.TO, addressListParser); - setFieldParser(Field.RESENT_TO, addressListParser); - setFieldParser(Field.CC, addressListParser); - setFieldParser(Field.RESENT_CC, addressListParser); - setFieldParser(Field.BCC, addressListParser); - setFieldParser(Field.RESENT_BCC, addressListParser); - setFieldParser(Field.REPLY_TO, addressListParser); - } -} diff --git a/apache/org/apache/james/mime4j/field/DelegatingFieldParser.java b/apache/org/apache/james/mime4j/field/DelegatingFieldParser.java deleted file mode 100644 index 32b69ec131e8776f9d1beec2f086ee40d54a71a2..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/DelegatingFieldParser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2006 the mime4j 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 org.apache.james.mime4j.field; - -import java.util.HashMap; -import java.util.Map; - -public class DelegatingFieldParser implements FieldParser { - - private Map parsers = new HashMap(); - private FieldParser defaultParser = new UnstructuredField.Parser(); - - /** - * Sets the parser used for the field named name. - * @param name the name of the field - * @param parser the parser for fields named name - */ - public void setFieldParser(final String name, final FieldParser parser) { - parsers.put(name.toLowerCase(), parser); - } - - public FieldParser getParser(final String name) { - final FieldParser field = parsers.get(name.toLowerCase()); - if(field==null) { - return defaultParser; - } - return field; - } - - public Field parse(final String name, final String body, final String raw) { - final FieldParser parser = getParser(name); - return parser.parse(name, body, raw); - } -} diff --git a/apache/org/apache/james/mime4j/field/Field.java b/apache/org/apache/james/mime4j/field/Field.java deleted file mode 100644 index 4dea5c5cfb6e0560b037f203ca26b5b36579dd48..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/Field.java +++ /dev/null @@ -1,192 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * The base class of all field classes. - * - * - * @version $Id: Field.java,v 1.6 2004/10/25 07:26:46 ntherning Exp $ - */ -public abstract class Field { - public static final String SENDER = "Sender"; - public static final String FROM = "From"; - public static final String TO = "To"; - public static final String CC = "Cc"; - public static final String BCC = "Bcc"; - public static final String REPLY_TO = "Reply-To"; - public static final String RESENT_SENDER = "Resent-Sender"; - public static final String RESENT_FROM = "Resent-From"; - public static final String RESENT_TO = "Resent-To"; - public static final String RESENT_CC = "Resent-Cc"; - public static final String RESENT_BCC = "Resent-Bcc"; - - public static final String DATE = "Date"; - public static final String RESENT_DATE = "Resent-Date"; - - public static final String SUBJECT = "Subject"; - public static final String CONTENT_TYPE = "Content-Type"; - public static final String CONTENT_TRANSFER_ENCODING = - "Content-Transfer-Encoding"; - - private static final String FIELD_NAME_PATTERN = - "^([\\x21-\\x39\\x3b-\\x7e]+)[ \t]*:"; - private static final Pattern fieldNamePattern = - Pattern.compile(FIELD_NAME_PATTERN); - - private static final DefaultFieldParser parser = new DefaultFieldParser(); - - private final String name; - private final String body; - private final String raw; - - protected Field(final String name, final String body, final String raw) { - this.name = name; - this.body = body; - this.raw = raw; - } - - /** - * Parses the given string and returns an instance of the - * Field class. The type of the class returned depends on - * the field name: - * - * - * - * - * - * - *
Field nameClass returnedContent-Typeorg.apache.james.mime4j.field.ContentTypeFieldotherorg.apache.james.mime4j.field.UnstructuredField
- * - * @param s the string to parse. - * @return a Field instance. - * @throws IllegalArgumentException on parse errors. - */ - public static Field parse(final String raw) { - - /* - * Unfold the field. - */ - final String unfolded = raw.replaceAll("\r|\n", ""); - - /* - * Split into name and value. - */ - final Matcher fieldMatcher = fieldNamePattern.matcher(unfolded); - if (!fieldMatcher.find()) { - throw new IllegalArgumentException("Invalid field in string"); - } - final String name = fieldMatcher.group(1); - - String body = unfolded.substring(fieldMatcher.end()); - if (body.length() > 0 && body.charAt(0) == ' ') { - body = body.substring(1); - } - - return parser.parse(name, body, raw); - } - - /** - * Gets the default parser used to parse fields. - * @return the default field parser - */ - public static DefaultFieldParser getParser() { - return parser; - } - - /** - * Gets the name of the field (Subject, - * From, etc). - * - * @return the field name. - */ - public String getName() { - return name; - } - - /** - * Gets the original raw field string. - * - * @return the original raw field string. - */ - public String getRaw() { - return raw; - } - - /** - * Gets the unfolded, unparsed and possibly encoded (see RFC 2047) field - * body string. - * - * @return the unfolded unparsed field body string. - */ - public String getBody() { - return body; - } - - /** - * Determines if this is a Content-Type field. - * - * @return true if this is a Content-Type field, - * false otherwise. - */ - public boolean isContentType() { - return CONTENT_TYPE.equalsIgnoreCase(name); - } - - /** - * Determines if this is a Subject field. - * - * @return true if this is a Subject field, - * false otherwise. - */ - public boolean isSubject() { - return SUBJECT.equalsIgnoreCase(name); - } - - /** - * Determines if this is a From field. - * - * @return true if this is a From field, - * false otherwise. - */ - public boolean isFrom() { - return FROM.equalsIgnoreCase(name); - } - - /** - * Determines if this is a To field. - * - * @return true if this is a To field, - * false otherwise. - */ - public boolean isTo() { - return TO.equalsIgnoreCase(name); - } - - /** - * @see #getRaw() - */ - public String toString() { - return raw; - } -} diff --git a/apache/org/apache/james/mime4j/field/FieldParser.java b/apache/org/apache/james/mime4j/field/FieldParser.java deleted file mode 100644 index 78aaf133497f3aff6b1db25461c72958bba869c1..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/FieldParser.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2006 the mime4j 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 org.apache.james.mime4j.field; - -public interface FieldParser { - - Field parse(final String name, final String body, final String raw); -} diff --git a/apache/org/apache/james/mime4j/field/MailboxField.java b/apache/org/apache/james/mime4j/field/MailboxField.java deleted file mode 100644 index f15980055e297e8237297a46adbdf6338c3cf455..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/MailboxField.java +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed -import org.apache.james.mime4j.field.address.AddressList; -import org.apache.james.mime4j.field.address.Mailbox; -import org.apache.james.mime4j.field.address.MailboxList; -import org.apache.james.mime4j.field.address.parser.ParseException; - -public class MailboxField extends Field { - private final Mailbox mailbox; - private final ParseException parseException; - - protected MailboxField(final String name, final String body, final String raw, final Mailbox mailbox, final ParseException parseException) { - super(name, body, raw); - this.mailbox = mailbox; - this.parseException = parseException; - } - - public Mailbox getMailbox() { - return mailbox; - } - - public ParseException getParseException() { - return parseException; - } - - public static class Parser implements FieldParser { - private static Log log = LogFactory.getLog(Parser.class); - - public Field parse(final String name, final String body, final String raw) { - Mailbox mailbox = null; - ParseException parseException = null; - try { - MailboxList mailboxList = AddressList.parse(body).flatten(); - if (mailboxList.size() > 0) { - mailbox = mailboxList.get(0); - } - } - catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug("Parsing value '" + body + "': "+ e.getMessage()); - } - parseException = e; - } - return new MailboxField(name, body, raw, mailbox, parseException); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/MailboxListField.java b/apache/org/apache/james/mime4j/field/MailboxListField.java deleted file mode 100644 index 23378d4fa463dec4c6b28eb05bd005eb2c220264..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/MailboxListField.java +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed -import org.apache.james.mime4j.field.address.AddressList; -import org.apache.james.mime4j.field.address.MailboxList; -import org.apache.james.mime4j.field.address.parser.ParseException; - -public class MailboxListField extends Field { - - private MailboxList mailboxList; - private ParseException parseException; - - protected MailboxListField(final String name, final String body, final String raw, final MailboxList mailboxList, final ParseException parseException) { - super(name, body, raw); - this.mailboxList = mailboxList; - this.parseException = parseException; - } - - public MailboxList getMailboxList() { - return mailboxList; - } - - public ParseException getParseException() { - return parseException; - } - - public static class Parser implements FieldParser { - private static Log log = LogFactory.getLog(Parser.class); - - public Field parse(final String name, final String body, final String raw) { - MailboxList mailboxList = null; - ParseException parseException = null; - try { - mailboxList = AddressList.parse(body).flatten(); - } - catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug("Parsing value '" + body + "': "+ e.getMessage()); - } - parseException = e; - } - return new MailboxListField(name, body, raw, mailboxList, parseException); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/UnstructuredField.java b/apache/org/apache/james/mime4j/field/UnstructuredField.java deleted file mode 100644 index 6084e44355be2623771c46c75b3a0ef76c35e3fb..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/UnstructuredField.java +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field; - -import org.apache.james.mime4j.decoder.DecoderUtil; - - -/** - * Simple unstructured field such as Subject. - * - * - * @version $Id: UnstructuredField.java,v 1.3 2004/10/25 07:26:46 ntherning Exp $ - */ -public class UnstructuredField extends Field { - private String value; - - protected UnstructuredField(String name, String body, String raw, String value) { - super(name, body, raw); - this.value = value; - } - - public String getValue() { - return value; - } - - public static class Parser implements FieldParser { - public Field parse(final String name, final String body, final String raw) { - final String value = DecoderUtil.decodeEncodedWords(body); - return new UnstructuredField(name, body, raw, value); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/address/Address.java b/apache/org/apache/james/mime4j/field/address/Address.java deleted file mode 100644 index 3e24e91aa9157f5a15b5d2b0ee1444628e7637f2..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/Address.java +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import java.util.ArrayList; - -/** - * The abstract base for classes that represent RFC2822 addresses. - * This includes groups and mailboxes. - * - * Currently, no public methods are introduced on this class. - * - * - */ -public abstract class Address { - - /** - * Adds any mailboxes represented by this address - * into the given ArrayList. Note that this method - * has default (package) access, so a doAddMailboxesTo - * method is needed to allow the behavior to be - * overridden by subclasses. - */ - final void addMailboxesTo(ArrayList

results) { - doAddMailboxesTo(results); - } - - /** - * Adds any mailboxes represented by this address - * into the given ArrayList. Must be overridden by - * concrete subclasses. - */ - protected abstract void doAddMailboxesTo(ArrayList
results); - -} diff --git a/apache/org/apache/james/mime4j/field/address/AddressList.java b/apache/org/apache/james/mime4j/field/address/AddressList.java deleted file mode 100644 index 1829e79aa53888fd9821e04ac46053196b515b3a..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/AddressList.java +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import org.apache.james.mime4j.field.address.parser.AddressListParser; -import org.apache.james.mime4j.field.address.parser.ParseException; - -import java.io.StringReader; -import java.util.ArrayList; - -/** - * An immutable, random-access list of Address objects. - * - * - */ -public class AddressList { - - private ArrayList
addresses; - - /** - * @param addresses An ArrayList that contains only Address objects. - * @param dontCopy true iff it is not possible for the addresses ArrayList to be modified by someone else. - */ - public AddressList(ArrayList
addresses, boolean dontCopy) { - if (addresses != null) - this.addresses = (dontCopy ? addresses : new ArrayList
(addresses)); - else - this.addresses = new ArrayList
(0); - } - - /** - * The number of elements in this list. - */ - public int size() { - return addresses.size(); - } - - /** - * Gets an address. - */ - public Address get(int index) { - if (0 > index || size() <= index) - throw new IndexOutOfBoundsException(); - return addresses.get(index); - } - - /** - * Returns a flat list of all mailboxes represented - * in this address list. Use this if you don't care - * about grouping. - */ - public MailboxList flatten() { - // in the common case, all addresses are mailboxes - boolean groupDetected = false; - for (int i = 0; i < size(); i++) { - if (!(get(i) instanceof Mailbox)) { - groupDetected = true; - break; - } - } - - if (!groupDetected) - return new MailboxList(addresses, true); - - ArrayList
results = new ArrayList
(); - for (int i = 0; i < size(); i++) { - Address addr = get(i); - addr.addMailboxesTo(results); - } - - // copy-on-construct this time, because subclasses - // could have held onto a reference to the results - return new MailboxList(results, false); - } - - /** - * Dumps a representation of this address list to - * stdout, for debugging purposes. - */ - public void print() { - for (int i = 0; i < size(); i++) { - Address addr = get(i); - System.out.println(addr.toString()); - } - } - - /** - * Parse the address list string, such as the value - * of a From, To, Cc, Bcc, Sender, or Reply-To - * header. - * - * The string MUST be unfolded already. - */ - public static AddressList parse(String rawAddressList) throws ParseException { - AddressListParser parser = new AddressListParser(new StringReader(rawAddressList)); - return Builder.getInstance().buildAddressList(parser.parse()); - } - - /** - * Test console. - */ - public static void main(String[] args) throws Exception { - java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); - while (true) { - try { - System.out.print("> "); - String line = reader.readLine(); - if (line.length() == 0 || line.toLowerCase().equals("exit") || line.toLowerCase().equals("quit")) { - System.out.println("Goodbye."); - return; - } - AddressList list = parse(line); - list.print(); - } - catch(Exception e) { - e.printStackTrace(); - Thread.sleep(300); - } - } - } -} diff --git a/apache/org/apache/james/mime4j/field/address/Builder.java b/apache/org/apache/james/mime4j/field/address/Builder.java deleted file mode 100644 index 3bcd15b6fc06e46244f4deca176036048d10779d..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/Builder.java +++ /dev/null @@ -1,243 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import java.util.ArrayList; -import java.util.Iterator; - -import org.apache.james.mime4j.decoder.DecoderUtil; -import org.apache.james.mime4j.field.address.parser.ASTaddr_spec; -import org.apache.james.mime4j.field.address.parser.ASTaddress; -import org.apache.james.mime4j.field.address.parser.ASTaddress_list; -import org.apache.james.mime4j.field.address.parser.ASTangle_addr; -import org.apache.james.mime4j.field.address.parser.ASTdomain; -import org.apache.james.mime4j.field.address.parser.ASTgroup_body; -import org.apache.james.mime4j.field.address.parser.ASTlocal_part; -import org.apache.james.mime4j.field.address.parser.ASTmailbox; -import org.apache.james.mime4j.field.address.parser.ASTname_addr; -import org.apache.james.mime4j.field.address.parser.ASTphrase; -import org.apache.james.mime4j.field.address.parser.ASTroute; -import org.apache.james.mime4j.field.address.parser.Node; -import org.apache.james.mime4j.field.address.parser.SimpleNode; -import org.apache.james.mime4j.field.address.parser.Token; - -/** - * Transforms the JJTree-generated abstract syntax tree - * into a graph of org.apache.james.mime4j.field.address objects. - * - * - */ -class Builder { - - private static Builder singleton = new Builder(); - - public static Builder getInstance() { - return singleton; - } - - - - public AddressList buildAddressList(ASTaddress_list node) { - ArrayList
list = new ArrayList
(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - ASTaddress childNode = (ASTaddress) node.jjtGetChild(i); - Address address = buildAddress(childNode); - list.add(address); - } - return new AddressList(list, true); - } - - private Address buildAddress(ASTaddress node) { - ChildNodeIterator it = new ChildNodeIterator(node); - Node n = it.nextNode(); - if (n instanceof ASTaddr_spec) { - return buildAddrSpec((ASTaddr_spec)n); - } - else if (n instanceof ASTangle_addr) { - return buildAngleAddr((ASTangle_addr)n); - } - else if (n instanceof ASTphrase) { - String name = buildString((ASTphrase)n, false); - Node n2 = it.nextNode(); - if (n2 instanceof ASTgroup_body) { - return new Group(name, buildGroupBody((ASTgroup_body)n2)); - } - else if (n2 instanceof ASTangle_addr) { - name = DecoderUtil.decodeEncodedWords(name); - return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2)); - } - else { - throw new IllegalStateException(); - } - } - else { - throw new IllegalStateException(); - } - } - - - - private MailboxList buildGroupBody(ASTgroup_body node) { - ArrayList
results = new ArrayList
(); - ChildNodeIterator it = new ChildNodeIterator(node); - while (it.hasNext()) { - Node n = it.nextNode(); - if (n instanceof ASTmailbox) - results.add(buildMailbox((ASTmailbox)n)); - else - throw new IllegalStateException(); - } - return new MailboxList(results, true); - } - - private Mailbox buildMailbox(ASTmailbox node) { - ChildNodeIterator it = new ChildNodeIterator(node); - Node n = it.nextNode(); - if (n instanceof ASTaddr_spec) { - return buildAddrSpec((ASTaddr_spec)n); - } - else if (n instanceof ASTangle_addr) { - return buildAngleAddr((ASTangle_addr)n); - } - else if (n instanceof ASTname_addr) { - return buildNameAddr((ASTname_addr)n); - } - else { - throw new IllegalStateException(); - } - } - - private NamedMailbox buildNameAddr(ASTname_addr node) { - ChildNodeIterator it = new ChildNodeIterator(node); - Node n = it.nextNode(); - String name; - if (n instanceof ASTphrase) { - name = buildString((ASTphrase)n, false); - } - else { - throw new IllegalStateException(); - } - - n = it.nextNode(); - if (n instanceof ASTangle_addr) { - name = DecoderUtil.decodeEncodedWords(name); - return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n)); - } - else { - throw new IllegalStateException(); - } - } - - private Mailbox buildAngleAddr(ASTangle_addr node) { - ChildNodeIterator it = new ChildNodeIterator(node); - DomainList route = null; - Node n = it.nextNode(); - if (n instanceof ASTroute) { - route = buildRoute((ASTroute)n); - n = it.nextNode(); - } - else if (n instanceof ASTaddr_spec) - ; // do nothing - else - throw new IllegalStateException(); - - if (n instanceof ASTaddr_spec) - return buildAddrSpec(route, (ASTaddr_spec)n); - else - throw new IllegalStateException(); - } - - private DomainList buildRoute(ASTroute node) { - ArrayList results = new ArrayList(node.jjtGetNumChildren()); - ChildNodeIterator it = new ChildNodeIterator(node); - while (it.hasNext()) { - Node n = it.nextNode(); - if (n instanceof ASTdomain) - results.add(buildString((ASTdomain)n, true)); - else - throw new IllegalStateException(); - } - return new DomainList(results, true); - } - - private Mailbox buildAddrSpec(ASTaddr_spec node) { - return buildAddrSpec(null, node); - } - private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) { - ChildNodeIterator it = new ChildNodeIterator(node); - String localPart = buildString((ASTlocal_part)it.nextNode(), true); - String domain = buildString((ASTdomain)it.nextNode(), true); - return new Mailbox(route, localPart, domain); - } - - - private String buildString(SimpleNode node, boolean stripSpaces) { - Token head = node.firstToken; - Token tail = node.lastToken; - StringBuffer out = new StringBuffer(); - - while (head != tail) { - out.append(head.image); - head = head.next; - if (!stripSpaces) - addSpecials(out, head.specialToken); - } - out.append(tail.image); - - return out.toString(); - } - - private void addSpecials(StringBuffer out, Token specialToken) { - if (specialToken != null) { - addSpecials(out, specialToken.specialToken); - out.append(specialToken.image); - } - } - - private static class ChildNodeIterator implements Iterator { - - private SimpleNode simpleNode; - private int index; - private int len; - - public ChildNodeIterator(SimpleNode simpleNode) { - this.simpleNode = simpleNode; - this.len = simpleNode.jjtGetNumChildren(); - this.index = 0; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public boolean hasNext() { - return index < len; - } - - public Node next() { - return nextNode(); - } - - public Node nextNode() { - return simpleNode.jjtGetChild(index++); - } - - } -} diff --git a/apache/org/apache/james/mime4j/field/address/DomainList.java b/apache/org/apache/james/mime4j/field/address/DomainList.java deleted file mode 100644 index 49b0f3be57e496f0d20f9f25caf3d4c00349789c..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/DomainList.java +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import java.util.ArrayList; - -/** - * An immutable, random-access list of Strings (that - * are supposedly domain names or domain literals). - * - * - */ -public class DomainList { - private ArrayList domains; - - /** - * @param domains An ArrayList that contains only String objects. - * @param dontCopy true iff it is not possible for the domains ArrayList to be modified by someone else. - */ - public DomainList(ArrayList domains, boolean dontCopy) { - if (domains != null) - this.domains = (dontCopy ? domains : new ArrayList(domains)); - else - this.domains = new ArrayList(0); - } - - /** - * The number of elements in this list. - */ - public int size() { - return domains.size(); - } - - /** - * Gets the domain name or domain literal at the - * specified index. - * @throws IndexOutOfBoundsException If index is < 0 or >= size(). - */ - public String get(int index) { - if (0 > index || size() <= index) - throw new IndexOutOfBoundsException(); - return domains.get(index); - } - - /** - * Returns the list of domains formatted as a route - * string (not including the trailing ':'). - */ - public String toRouteString() { - StringBuffer out = new StringBuffer(); - for (int i = 0; i < domains.size(); i++) { - out.append("@"); - out.append(get(i)); - if (i + 1 < domains.size()) - out.append(","); - } - return out.toString(); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/Group.java b/apache/org/apache/james/mime4j/field/address/Group.java deleted file mode 100644 index c0ab7f724972941465dc19b57f8b6722d3d58241..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/Group.java +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import java.util.ArrayList; - -/** - * A named group of zero or more mailboxes. - * - * - */ -public class Group extends Address { - private String name; - private MailboxList mailboxList; - - /** - * @param name The group name. - * @param mailboxes The mailboxes in this group. - */ - public Group(String name, MailboxList mailboxes) { - this.name = name; - this.mailboxList = mailboxes; - } - - /** - * Returns the group name. - */ - public String getName() { - return name; - } - - /** - * Returns the mailboxes in this group. - */ - public MailboxList getMailboxes() { - return mailboxList; - } - - @Override - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append(name); - buf.append(":"); - for (int i = 0; i < mailboxList.size(); i++) { - buf.append(mailboxList.get(i).toString()); - if (i + 1 < mailboxList.size()) - buf.append(","); - } - buf.append(";"); - return buf.toString(); - } - - @Override - protected void doAddMailboxesTo(ArrayList
results) { - for (int i = 0; i < mailboxList.size(); i++) - results.add(mailboxList.get(i)); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/Mailbox.java b/apache/org/apache/james/mime4j/field/address/Mailbox.java deleted file mode 100644 index 25f2548d4578c4ca202e71efc7508b1d91a44f73..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/Mailbox.java +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import java.util.ArrayList; - -/** - * Represents a single e-mail address. - * - * - */ -public class Mailbox extends Address { - private DomainList route; - private String localPart; - private String domain; - - /** - * Creates a mailbox without a route. Routes are obsolete. - * @param localPart The part of the e-mail address to the left of the "@". - * @param domain The part of the e-mail address to the right of the "@". - */ - public Mailbox(String localPart, String domain) { - this(null, localPart, domain); - } - - /** - * Creates a mailbox with a route. Routes are obsolete. - * @param route The zero or more domains that make up the route. Can be null. - * @param localPart The part of the e-mail address to the left of the "@". - * @param domain The part of the e-mail address to the right of the "@". - */ - public Mailbox(DomainList route, String localPart, String domain) { - this.route = route; - this.localPart = localPart; - this.domain = domain; - } - - /** - * Returns the route list. - */ - public DomainList getRoute() { - return route; - } - - /** - * Returns the left part of the e-mail address - * (before "@"). - */ - public String getLocalPart() { - return localPart; - } - - /** - * Returns the right part of the e-mail address - * (after "@"). - */ - public String getDomain() { - return domain; - } - - /** - * Formats the address as a string, not including - * the route. - * - * @see #getAddressString(boolean) - */ - public String getAddressString() { - return getAddressString(false); - } - - /** - * Note that this value may not be usable - * for transport purposes, only display purposes. - * - * For example, if the unparsed address was - * - * <"Joe Cheng"@joecheng.com> - * - * this method would return - * - * - * - * which is not valid for transport; the local part - * would need to be re-quoted. - * - * @param includeRoute true if the route should be included if it exists. - */ - public String getAddressString(boolean includeRoute) { - return "<" + (!includeRoute || route == null ? "" : route.toRouteString() + ":") - + localPart - + (domain == null ? "" : "@") - + domain + ">"; - } - - @Override - protected final void doAddMailboxesTo(ArrayList
results) { - results.add(this); - } - - @Override - public String toString() { - return getAddressString(); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/MailboxList.java b/apache/org/apache/james/mime4j/field/address/MailboxList.java deleted file mode 100644 index 2c9efb37fde7d6204b7e63fbf65ec2be8a4a274f..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/MailboxList.java +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -import java.util.ArrayList; - -/** - * An immutable, random-access list of Mailbox objects. - * - * - */ -public class MailboxList { - - private ArrayList
mailboxes; - - /** - * @param mailboxes An ArrayList that contains only Mailbox objects. - * @param dontCopy true iff it is not possible for the mailboxes ArrayList to be modified by someone else. - */ - public MailboxList(ArrayList
mailboxes, boolean dontCopy) { - if (mailboxes != null) - this.mailboxes = (dontCopy ? mailboxes : new ArrayList
(mailboxes)); - else - this.mailboxes = new ArrayList
(0); - } - - /** - * The number of elements in this list. - */ - public int size() { - return mailboxes.size(); - } - - /** - * Gets an address. - */ - public Mailbox get(int index) { - if (0 > index || size() <= index) - throw new IndexOutOfBoundsException(); - return (Mailbox)mailboxes.get(index); - } - - /** - * Dumps a representation of this mailbox list to - * stdout, for debugging purposes. - */ - public void print() { - for (int i = 0; i < size(); i++) { - Mailbox mailbox = get(i); - System.out.println(mailbox.toString()); - } - } - -} diff --git a/apache/org/apache/james/mime4j/field/address/NamedMailbox.java b/apache/org/apache/james/mime4j/field/address/NamedMailbox.java deleted file mode 100644 index 4b8306037b244c96c661f328c96701ea16f80cad..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/NamedMailbox.java +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address; - -/** - * A Mailbox that has a name/description. - * - * - */ -public class NamedMailbox extends Mailbox { - private String name; - - /** - * @see Mailbox#Mailbox(String, String) - */ - public NamedMailbox(String name, String localPart, String domain) { - super(localPart, domain); - this.name = name; - } - - /** - * @see Mailbox#Mailbox(DomainList, String, String) - */ - public NamedMailbox(String name, DomainList route, String localPart, String domain) { - super(route, localPart, domain); - this.name = name; - } - - /** - * Creates a named mailbox based on an unnamed mailbox. - */ - public NamedMailbox(String name, Mailbox baseMailbox) { - super(baseMailbox.getRoute(), baseMailbox.getLocalPart(), baseMailbox.getDomain()); - this.name = name; - } - - /** - * Returns the name of the mailbox. - */ - public String getName() { - return this.name; - } - - /** - * Same features (or problems) as Mailbox.getAddressString(boolean), - * only more so. - * - * @see Mailbox#getAddressString(boolean) - */ - @Override - public String getAddressString(boolean includeRoute) { - return (name == null ? "" : name + " ") + super.getAddressString(includeRoute); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java b/apache/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java deleted file mode 100644 index 4d56d000b02e469495b69c1349515118e1f200e6..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTaddr_spec.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTaddr_spec.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTaddr_spec extends SimpleNode { - public ASTaddr_spec(int id) { - super(id); - } - - public ASTaddr_spec(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTaddress.java b/apache/org/apache/james/mime4j/field/address/parser/ASTaddress.java deleted file mode 100644 index 47bdeda8ee15dd2babba8b31fc2b6357bbcacbd1..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTaddress.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTaddress.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTaddress extends SimpleNode { - public ASTaddress(int id) { - super(id); - } - - public ASTaddress(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java b/apache/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java deleted file mode 100644 index 737840e386542da4b5f047b9ac4902e2ca710694..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTaddress_list.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTaddress_list.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTaddress_list extends SimpleNode { - public ASTaddress_list(int id) { - super(id); - } - - public ASTaddress_list(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java b/apache/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java deleted file mode 100644 index 8cb8f421f0360de28df633faa21bda00cfe9ccb4..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTangle_addr.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTangle_addr.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTangle_addr extends SimpleNode { - public ASTangle_addr(int id) { - super(id); - } - - public ASTangle_addr(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTdomain.java b/apache/org/apache/james/mime4j/field/address/parser/ASTdomain.java deleted file mode 100644 index b5266438639648db8af2c0d3baca32a75fd36dc9..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTdomain.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTdomain.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTdomain extends SimpleNode { - public ASTdomain(int id) { - super(id); - } - - public ASTdomain(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java b/apache/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java deleted file mode 100644 index f6017b9fc5d6de1b1912172d742634ddd7ef200d..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTgroup_body.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTgroup_body.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTgroup_body extends SimpleNode { - public ASTgroup_body(int id) { - super(id); - } - - public ASTgroup_body(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java b/apache/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java deleted file mode 100644 index 5c244fa3e87f9ce25d672706ded9cd33c9abf667..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTlocal_part.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTlocal_part.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTlocal_part extends SimpleNode { - public ASTlocal_part(int id) { - super(id); - } - - public ASTlocal_part(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTmailbox.java b/apache/org/apache/james/mime4j/field/address/parser/ASTmailbox.java deleted file mode 100644 index aeb469da16055ba83341425a3fa9e558f04a02b6..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTmailbox.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTmailbox.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTmailbox extends SimpleNode { - public ASTmailbox(int id) { - super(id); - } - - public ASTmailbox(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTname_addr.java b/apache/org/apache/james/mime4j/field/address/parser/ASTname_addr.java deleted file mode 100644 index 846c731671aa4afd1e7ba943f83b0e06012c19b7..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTname_addr.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTname_addr.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTname_addr extends SimpleNode { - public ASTname_addr(int id) { - super(id); - } - - public ASTname_addr(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTphrase.java b/apache/org/apache/james/mime4j/field/address/parser/ASTphrase.java deleted file mode 100644 index 7d711c52904fdf6eb5eb1abb8be780b371250661..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTphrase.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTphrase.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTphrase extends SimpleNode { - public ASTphrase(int id) { - super(id); - } - - public ASTphrase(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ASTroute.java b/apache/org/apache/james/mime4j/field/address/parser/ASTroute.java deleted file mode 100644 index 54ea11523c6e8e9520fdf77a90ba57d5863e1ac3..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ASTroute.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. ASTroute.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class ASTroute extends SimpleNode { - public ASTroute(int id) { - super(id); - } - - public ASTroute(AddressListParser p, int id) { - super(p, id); - } - - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/AddressListParser.java b/apache/org/apache/james/mime4j/field/address/parser/AddressListParser.java deleted file mode 100644 index 8094df0ad5ae416017aac60309018d9702e83bb1..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/AddressListParser.java +++ /dev/null @@ -1,977 +0,0 @@ -/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParser.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -public class AddressListParser/*@bgen(jjtree)*/implements AddressListParserTreeConstants, AddressListParserConstants {/*@bgen(jjtree)*/ - protected JJTAddressListParserState jjtree = new JJTAddressListParserState();public static void main(String args[]) throws ParseException { - while (true) { - try { - AddressListParser parser = new AddressListParser(System.in); - parser.parseLine(); - ((SimpleNode)parser.jjtree.rootNode()).dump("> "); - } catch (Exception x) { - x.printStackTrace(); - return; - } - } - } - - private static void log(String msg) { - System.out.print(msg); - } - - public ASTaddress_list parse() throws ParseException { - try { - parseAll(); - return (ASTaddress_list)jjtree.rootNode(); - } catch (TokenMgrError tme) { - throw new ParseException(tme.getMessage()); - } - } - - - void jjtreeOpenNodeScope(Node n) { - ((SimpleNode)n).firstToken = getToken(1); - } - - void jjtreeCloseNodeScope(Node n) { - ((SimpleNode)n).lastToken = getToken(0); - } - - final public void parseLine() throws ParseException { - address_list(); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 1: - jj_consume_token(1); - break; - default: - jj_la1[0] = jj_gen; - ; - } - jj_consume_token(2); - } - - final public void parseAll() throws ParseException { - address_list(); - jj_consume_token(0); - } - - final public void address_list() throws ParseException { - /*@bgen(jjtree) address_list */ - ASTaddress_list jjtn000 = new ASTaddress_list(JJTADDRESS_LIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 6: - case DOTATOM: - case QUOTEDSTRING: - address(); - break; - default: - jj_la1[1] = jj_gen; - ; - } - label_1: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 3: - ; - break; - default: - jj_la1[2] = jj_gen; - break label_1; - } - jj_consume_token(3); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 6: - case DOTATOM: - case QUOTEDSTRING: - address(); - break; - default: - jj_la1[3] = jj_gen; - ; - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void address() throws ParseException { - /*@bgen(jjtree) address */ - ASTaddress jjtn000 = new ASTaddress(JJTADDRESS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_1(2147483647)) { - addr_spec(); - } else { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 6: - angle_addr(); - break; - case DOTATOM: - case QUOTEDSTRING: - phrase(); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 4: - group_body(); - break; - case 6: - angle_addr(); - break; - default: - jj_la1[4] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_la1[5] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void mailbox() throws ParseException { - /*@bgen(jjtree) mailbox */ - ASTmailbox jjtn000 = new ASTmailbox(JJTMAILBOX); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_2(2147483647)) { - addr_spec(); - } else { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 6: - angle_addr(); - break; - case DOTATOM: - case QUOTEDSTRING: - name_addr(); - break; - default: - jj_la1[6] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void name_addr() throws ParseException { - /*@bgen(jjtree) name_addr */ - ASTname_addr jjtn000 = new ASTname_addr(JJTNAME_ADDR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - phrase(); - angle_addr(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void group_body() throws ParseException { - /*@bgen(jjtree) group_body */ - ASTgroup_body jjtn000 = new ASTgroup_body(JJTGROUP_BODY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(4); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 6: - case DOTATOM: - case QUOTEDSTRING: - mailbox(); - break; - default: - jj_la1[7] = jj_gen; - ; - } - label_2: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 3: - ; - break; - default: - jj_la1[8] = jj_gen; - break label_2; - } - jj_consume_token(3); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 6: - case DOTATOM: - case QUOTEDSTRING: - mailbox(); - break; - default: - jj_la1[9] = jj_gen; - ; - } - } - jj_consume_token(5); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void angle_addr() throws ParseException { - /*@bgen(jjtree) angle_addr */ - ASTangle_addr jjtn000 = new ASTangle_addr(JJTANGLE_ADDR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(6); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 8: - route(); - break; - default: - jj_la1[10] = jj_gen; - ; - } - addr_spec(); - jj_consume_token(7); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void route() throws ParseException { - /*@bgen(jjtree) route */ - ASTroute jjtn000 = new ASTroute(JJTROUTE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(8); - domain(); - label_3: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 3: - case 8: - ; - break; - default: - jj_la1[11] = jj_gen; - break label_3; - } - label_4: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 3: - ; - break; - default: - jj_la1[12] = jj_gen; - break label_4; - } - jj_consume_token(3); - } - jj_consume_token(8); - domain(); - } - jj_consume_token(4); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void phrase() throws ParseException { - /*@bgen(jjtree) phrase */ - ASTphrase jjtn000 = new ASTphrase(JJTPHRASE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - label_5: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case DOTATOM: - jj_consume_token(DOTATOM); - break; - case QUOTEDSTRING: - jj_consume_token(QUOTEDSTRING); - break; - default: - jj_la1[13] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case DOTATOM: - case QUOTEDSTRING: - ; - break; - default: - jj_la1[14] = jj_gen; - break label_5; - } - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void addr_spec() throws ParseException { - /*@bgen(jjtree) addr_spec */ - ASTaddr_spec jjtn000 = new ASTaddr_spec(JJTADDR_SPEC); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - local_part(); - jj_consume_token(8); - domain(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - {if (true) throw (RuntimeException)jjte000;} - } - if (jjte000 instanceof ParseException) { - {if (true) throw (ParseException)jjte000;} - } - {if (true) throw (Error)jjte000;} - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void local_part() throws ParseException { - /*@bgen(jjtree) local_part */ - ASTlocal_part jjtn000 = new ASTlocal_part(JJTLOCAL_PART); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000);Token t; - try { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case DOTATOM: - t = jj_consume_token(DOTATOM); - break; - case QUOTEDSTRING: - t = jj_consume_token(QUOTEDSTRING); - break; - default: - jj_la1[15] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_6: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 9: - case DOTATOM: - case QUOTEDSTRING: - ; - break; - default: - jj_la1[16] = jj_gen; - break label_6; - } - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 9: - t = jj_consume_token(9); - break; - default: - jj_la1[17] = jj_gen; - ; - } - if (t.image.charAt(t.image.length() - 1) != '.' || t.kind == AddressListParserConstants.QUOTEDSTRING) - {if (true) throw new ParseException("Words in local part must be separated by '.'");} - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case DOTATOM: - t = jj_consume_token(DOTATOM); - break; - case QUOTEDSTRING: - t = jj_consume_token(QUOTEDSTRING); - break; - default: - jj_la1[18] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void domain() throws ParseException { - /*@bgen(jjtree) domain */ - ASTdomain jjtn000 = new ASTdomain(JJTDOMAIN); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000);Token t; - try { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case DOTATOM: - t = jj_consume_token(DOTATOM); - label_7: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 9: - case DOTATOM: - ; - break; - default: - jj_la1[19] = jj_gen; - break label_7; - } - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 9: - t = jj_consume_token(9); - break; - default: - jj_la1[20] = jj_gen; - ; - } - if (t.image.charAt(t.image.length() - 1) != '.') - {if (true) throw new ParseException("Atoms in domain names must be separated by '.'");} - t = jj_consume_token(DOTATOM); - } - break; - case DOMAINLITERAL: - jj_consume_token(DOMAINLITERAL); - break; - default: - jj_la1[21] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final private boolean jj_2_1(int xla) { - jj_la = xla; jj_lastpos = jj_scanpos = token; - try { return !jj_3_1(); } - catch(LookaheadSuccess ls) { return true; } - finally { jj_save(0, xla); } - } - - final private boolean jj_2_2(int xla) { - jj_la = xla; jj_lastpos = jj_scanpos = token; - try { return !jj_3_2(); } - catch(LookaheadSuccess ls) { return true; } - finally { jj_save(1, xla); } - } - - final private boolean jj_3R_11() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(9)) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_scan_token(14)) { - jj_scanpos = xsp; - if (jj_scan_token(31)) return true; - } - return false; - } - - final private boolean jj_3R_13() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(9)) jj_scanpos = xsp; - if (jj_scan_token(DOTATOM)) return true; - return false; - } - - final private boolean jj_3R_8() { - if (jj_3R_9()) return true; - if (jj_scan_token(8)) return true; - if (jj_3R_10()) return true; - return false; - } - - final private boolean jj_3_1() { - if (jj_3R_8()) return true; - return false; - } - - final private boolean jj_3R_12() { - if (jj_scan_token(DOTATOM)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_13()) { jj_scanpos = xsp; break; } - } - return false; - } - - final private boolean jj_3R_10() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_12()) { - jj_scanpos = xsp; - if (jj_scan_token(18)) return true; - } - return false; - } - - final private boolean jj_3_2() { - if (jj_3R_8()) return true; - return false; - } - - final private boolean jj_3R_9() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(14)) { - jj_scanpos = xsp; - if (jj_scan_token(31)) return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_3R_11()) { jj_scanpos = xsp; break; } - } - return false; - } - - public AddressListParserTokenManager token_source; - SimpleCharStream jj_input_stream; - public Token token, jj_nt; - private int jj_ntk; - private Token jj_scanpos, jj_lastpos; - private int jj_la; - public boolean lookingAhead = false; - private boolean jj_semLA; - private int jj_gen; - final private int[] jj_la1 = new int[22]; - static private int[] jj_la1_0; - static private int[] jj_la1_1; - static { - jj_la1_0(); - jj_la1_1(); - } - private static void jj_la1_0() { - jj_la1_0 = new int[] {0x2,0x80004040,0x8,0x80004040,0x50,0x80004040,0x80004040,0x80004040,0x8,0x80004040,0x100,0x108,0x8,0x80004000,0x80004000,0x80004000,0x80004200,0x200,0x80004000,0x4200,0x200,0x44000,}; - } - private static void jj_la1_1() { - jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; - } - final private JJCalls[] jj_2_rtns = new JJCalls[2]; - private boolean jj_rescan = false; - private int jj_gc = 0; - - public AddressListParser(java.io.InputStream stream) { - this(stream, null); - } - public AddressListParser(java.io.InputStream stream, String encoding) { - try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source = new AddressListParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 22; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - public void ReInit(java.io.InputStream stream, String encoding) { - try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - jj_gen = 0; - for (int i = 0; i < 22; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - public AddressListParser(java.io.Reader stream) { - jj_input_stream = new SimpleCharStream(stream, 1, 1); - token_source = new AddressListParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 22; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - public void ReInit(java.io.Reader stream) { - jj_input_stream.ReInit(stream, 1, 1); - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - jj_gen = 0; - for (int i = 0; i < 22; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - public AddressListParser(AddressListParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 22; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - public void ReInit(AddressListParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - jj_gen = 0; - for (int i = 0; i < 22; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - final private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - if (token.kind == kind) { - jj_gen++; - if (++jj_gc > 100) { - jj_gc = 0; - for (int i = 0; i < jj_2_rtns.length; i++) { - JJCalls c = jj_2_rtns[i]; - while (c != null) { - if (c.gen < jj_gen) c.first = null; - c = c.next; - } - } - } - return token; - } - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - static private final class LookaheadSuccess extends java.lang.Error { } - final private LookaheadSuccess jj_ls = new LookaheadSuccess(); - final private boolean jj_scan_token(int kind) { - if (jj_scanpos == jj_lastpos) { - jj_la--; - if (jj_scanpos.next == null) { - jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); - } else { - jj_lastpos = jj_scanpos = jj_scanpos.next; - } - } else { - jj_scanpos = jj_scanpos.next; - } - if (jj_rescan) { - int i = 0; Token tok = token; - while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } - if (tok != null) jj_add_error_token(kind, i); - } - if (jj_scanpos.kind != kind) return true; - if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; - return false; - } - - final public Token getNextToken() { - if (token.next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - jj_gen++; - return token; - } - - final public Token getToken(int index) { - Token t = lookingAhead ? jj_scanpos : token; - for (int i = 0; i < index; i++) { - if (t.next != null) t = t.next; - else t = t.next = token_source.getNextToken(); - } - return t; - } - - final private int jj_ntk() { - if ((jj_nt=token.next) == null) - return (jj_ntk = (token.next=token_source.getNextToken()).kind); - else - return (jj_ntk = jj_nt.kind); - } - - private java.util.Vector jj_expentries = new java.util.Vector(); - private int[] jj_expentry; - private int jj_kind = -1; - private int[] jj_lasttokens = new int[100]; - private int jj_endpos; - - private void jj_add_error_token(int kind, int pos) { - if (pos >= 100) return; - if (pos == jj_endpos + 1) { - jj_lasttokens[jj_endpos++] = kind; - } else if (jj_endpos != 0) { - jj_expentry = new int[jj_endpos]; - for (int i = 0; i < jj_endpos; i++) { - jj_expentry[i] = jj_lasttokens[i]; - } - boolean exists = false; - for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) { - int[] oldentry = e.nextElement(); - if (oldentry.length == jj_expentry.length) { - exists = true; - for (int i = 0; i < jj_expentry.length; i++) { - if (oldentry[i] != jj_expentry[i]) { - exists = false; - break; - } - } - if (exists) break; - } - } - if (!exists) jj_expentries.addElement(jj_expentry); - if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; - } - } - - public ParseException generateParseException() { - jj_expentries.removeAllElements(); - boolean[] la1tokens = new boolean[34]; - for (int i = 0; i < 34; i++) { - la1tokens[i] = false; - } - if (jj_kind >= 0) { - la1tokens[jj_kind] = true; - jj_kind = -1; - } - for (int i = 0; i < 22; i++) { - if (jj_la1[i] == jj_gen) { - for (int j = 0; j < 32; j++) { - if ((jj_la1_0[i] & (1< jj_gen) { - jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; - switch (i) { - case 0: jj_3_1(); break; - case 1: jj_3_2(); break; - } - } - p = p.next; - } while (p != null); - } catch(LookaheadSuccess ls) { } - } - jj_rescan = false; - } - - final private void jj_save(int index, int xla) { - JJCalls p = jj_2_rtns[index]; - while (p.gen > jj_gen) { - if (p.next == null) { p = p.next = new JJCalls(); break; } - p = p.next; - } - p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; - } - - static final class JJCalls { - int gen; - Token first; - int arg; - JJCalls next; - } - -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/AddressListParser.jj b/apache/org/apache/james/mime4j/field/address/parser/AddressListParser.jj deleted file mode 100644 index c14277bc6019ce24ccae4fa95fccc1cf5b88c315..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/AddressListParser.jj +++ /dev/null @@ -1,595 +0,0 @@ -/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParser.jj */ -/*@egen*//**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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. * - ****************************************************************/ - - -/** - * RFC2822 address list parser. - * - * Created 9/17/2004 - * by Joe Cheng - */ - -options { - STATIC=false; - LOOKAHEAD=1; - //DEBUG_PARSER=true; - //DEBUG_TOKEN_MANAGER=true; -} - -PARSER_BEGIN(AddressListParser) -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -public class AddressListParser/*@bgen(jjtree)*/implements AddressListParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/ - protected JJTAddressListParserState jjtree = new JJTAddressListParserState(); - -/*@egen*/ - public static void main(String args[]) throws ParseException { - while (true) { - try { - AddressListParser parser = new AddressListParser(System.in); - parser.parseLine(); - ((SimpleNode)parser.jjtree.rootNode()).dump("> "); - } catch (Exception x) { - x.printStackTrace(); - return; - } - } - } - - private static void log(String msg) { - System.out.print(msg); - } - - public ASTaddress_list parse() throws ParseException { - try { - parseAll(); - return (ASTaddress_list)jjtree.rootNode(); - } catch (TokenMgrError tme) { - throw new ParseException(tme.getMessage()); - } - } - - - void jjtreeOpenNodeScope(Node n) { - ((SimpleNode)n).firstToken = getToken(1); - } - - void jjtreeCloseNodeScope(Node n) { - ((SimpleNode)n).lastToken = getToken(0); - } -} - -PARSER_END(AddressListParser) - -void parseLine() : -{} -{ - address_list() ["\r"] "\n" -} - -void parseAll() : -{} -{ - address_list() -} - -void address_list() : -{/*@bgen(jjtree) address_list */ - ASTaddress_list jjtn000 = new ASTaddress_list(JJTADDRESS_LIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) address_list */ - try { -/*@egen*/ - [ address() ] - ( - "," - [ address() ] - )*/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void address() : -{/*@bgen(jjtree) address */ - ASTaddress jjtn000 = new ASTaddress(JJTADDRESS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) address */ - try { -/*@egen*/ - LOOKAHEAD(2147483647) - addr_spec() -| angle_addr() -| ( phrase() (group_body() | angle_addr()) )/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void mailbox() : -{/*@bgen(jjtree) mailbox */ - ASTmailbox jjtn000 = new ASTmailbox(JJTMAILBOX); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) mailbox */ - try { -/*@egen*/ - LOOKAHEAD(2147483647) - addr_spec() -| angle_addr() -| name_addr()/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void name_addr() : -{/*@bgen(jjtree) name_addr */ - ASTname_addr jjtn000 = new ASTname_addr(JJTNAME_ADDR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) name_addr */ - try { -/*@egen*/ - phrase() angle_addr()/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void group_body() : -{/*@bgen(jjtree) group_body */ - ASTgroup_body jjtn000 = new ASTgroup_body(JJTGROUP_BODY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) group_body */ - try { -/*@egen*/ - ":" - [ mailbox() ] - ( - "," - [ mailbox() ] - )* - ";"/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void angle_addr() : -{/*@bgen(jjtree) angle_addr */ - ASTangle_addr jjtn000 = new ASTangle_addr(JJTANGLE_ADDR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) angle_addr */ - try { -/*@egen*/ - "<" [ route() ] addr_spec() ">"/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void route() : -{/*@bgen(jjtree) route */ - ASTroute jjtn000 = new ASTroute(JJTROUTE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) route */ - try { -/*@egen*/ - "@" domain() ( (",")* "@" domain() )* ":"/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void phrase() : -{/*@bgen(jjtree) phrase */ - ASTphrase jjtn000 = new ASTphrase(JJTPHRASE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) phrase */ -try { -/*@egen*/ -( -| -)+/*@bgen(jjtree)*/ -} finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } -} -/*@egen*/ -} - -void addr_spec() : -{/*@bgen(jjtree) addr_spec */ - ASTaddr_spec jjtn000 = new ASTaddr_spec(JJTADDR_SPEC); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/} -{/*@bgen(jjtree) addr_spec */ - try { -/*@egen*/ - ( local_part() "@" domain() )/*@bgen(jjtree)*/ - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - throw (RuntimeException)jjte000; - } - if (jjte000 instanceof ParseException) { - throw (ParseException)jjte000; - } - throw (Error)jjte000; - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void local_part() : -{/*@bgen(jjtree) local_part */ - ASTlocal_part jjtn000 = new ASTlocal_part(JJTLOCAL_PART); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/ Token t; } -{/*@bgen(jjtree) local_part */ - try { -/*@egen*/ - ( t= | t= ) - ( [t="."] - { - if (t.image.charAt(t.image.length() - 1) != '.' || t.kind == AddressListParserConstants.QUOTEDSTRING) - throw new ParseException("Words in local part must be separated by '.'"); - } - ( t= | t= ) - )*/*@bgen(jjtree)*/ - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -void domain() : -{/*@bgen(jjtree) domain */ - ASTdomain jjtn000 = new ASTdomain(JJTDOMAIN); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); -/*@egen*/ Token t; } -{/*@bgen(jjtree) domain */ - try { -/*@egen*/ - ( t= - ( [t="."] - { - if (t.image.charAt(t.image.length() - 1) != '.') - throw new ParseException("Atoms in domain names must be separated by '.'"); - } - t= - )* - ) -| /*@bgen(jjtree)*/ - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } -/*@egen*/ -} - -SPECIAL_TOKEN : -{ - < WS: ( [" ", "\t"] )+ > -} - -TOKEN : -{ - < #ALPHA: ["a" - "z", "A" - "Z"] > -| < #DIGIT: ["0" - "9"] > -| < #ATEXT: ( | - | "!" | "#" | "$" | "%" - | "&" | "'" | "*" | "+" - | "-" | "/" | "=" | "?" - | "^" | "_" | "`" | "{" - | "|" | "}" | "~" - )> -| < DOTATOM: ( | "." )* > -} - -TOKEN_MGR_DECLS : -{ - // Keeps track of how many levels of comment nesting - // we've encountered. This is only used when the 2nd - // level is reached, for example ((this)), not (this). - // This is because the outermost level must be treated - // specially anyway, because the outermost ")" has a - // different token type than inner ")" instances. - static int commentNest; -} - -MORE : -{ - // domain literal - "[" : INDOMAINLITERAL -} - - -MORE : -{ - < > { image.deleteCharAt(image.length() - 2); } -| < ~["[", "]", "\\"] > -} - - -TOKEN : -{ - < DOMAINLITERAL: "]" > { matchedToken.image = image.toString(); }: DEFAULT -} - -MORE : -{ - // starts a comment - "(" : INCOMMENT -} - - -SKIP : -{ - // ends a comment - < COMMENT: ")" > : DEFAULT - // if this is ever changed to not be a SKIP, need - // to make sure matchedToken.token = token.toString() - // is called. -} - - -MORE : -{ - < > { image.deleteCharAt(image.length() - 2); } -| "(" { commentNest = 1; } : NESTED_COMMENT -| < > -} - - -MORE : -{ - < > { image.deleteCharAt(image.length() - 2); } -| "(" { ++commentNest; } -| ")" { --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); } -| < > -} - - -// QUOTED STRINGS - -MORE : -{ - "\"" { image.deleteCharAt(image.length() - 1); } : INQUOTEDSTRING -} - - -MORE : -{ - < > { image.deleteCharAt(image.length() - 2); } -| < (~["\"", "\\"])+ > -} - - -TOKEN : -{ - < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT -} - -// GLOBALS - -<*> -TOKEN : -{ - < #QUOTEDPAIR: "\\" > -| < #ANY: ~[] > -} - -// ERROR! -/* - -<*> -TOKEN : -{ - < UNEXPECTED_CHAR: > -} - -*/ \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java b/apache/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java deleted file mode 100644 index 006a082c1eae4e317a4e6a2778d75c6977f0d251..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserConstants.java +++ /dev/null @@ -1,76 +0,0 @@ -/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParserConstants.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -public interface AddressListParserConstants { - - int EOF = 0; - int WS = 10; - int ALPHA = 11; - int DIGIT = 12; - int ATEXT = 13; - int DOTATOM = 14; - int DOMAINLITERAL = 18; - int COMMENT = 20; - int QUOTEDSTRING = 31; - int QUOTEDPAIR = 32; - int ANY = 33; - - int DEFAULT = 0; - int INDOMAINLITERAL = 1; - int INCOMMENT = 2; - int NESTED_COMMENT = 3; - int INQUOTEDSTRING = 4; - - String[] tokenImage = { - "", - "\"\\r\"", - "\"\\n\"", - "\",\"", - "\":\"", - "\";\"", - "\"<\"", - "\">\"", - "\"@\"", - "\".\"", - "", - "", - "", - "", - "", - "\"[\"", - "", - "", - "\"]\"", - "\"(\"", - "\")\"", - "", - "\"(\"", - "", - "", - "\"(\"", - "\")\"", - "", - "\"\\\"\"", - "", - "", - "\"\\\"\"", - "", - "", - }; - -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java b/apache/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java deleted file mode 100644 index d2dd88dd3d2d486c728bf3cb97e62b412e2af093..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserTokenManager.java +++ /dev/null @@ -1,1009 +0,0 @@ -/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParserTokenManager.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -public class AddressListParserTokenManager implements AddressListParserConstants -{ - // Keeps track of how many levels of comment nesting - // we've encountered. This is only used when the 2nd - // level is reached, for example ((this)), not (this). - // This is because the outermost level must be treated - // specially anyway, because the outermost ")" has a - // different token type than inner ")" instances. - static int commentNest; - public java.io.PrintStream debugStream = System.out; - public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } -private final int jjStopStringLiteralDfa_0(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_0(int pos, long active0) -{ - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); -} -private final int jjStopAtPos(int pos, int kind) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; -} -private final int jjStartNfaWithStates_0(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_0(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_0() -{ - switch(curChar) - { - case 10: - return jjStopAtPos(0, 2); - case 13: - return jjStopAtPos(0, 1); - case 34: - return jjStopAtPos(0, 28); - case 40: - return jjStopAtPos(0, 19); - case 44: - return jjStopAtPos(0, 3); - case 46: - return jjStopAtPos(0, 9); - case 58: - return jjStopAtPos(0, 4); - case 59: - return jjStopAtPos(0, 5); - case 60: - return jjStopAtPos(0, 6); - case 62: - return jjStopAtPos(0, 7); - case 64: - return jjStopAtPos(0, 8); - case 91: - return jjStopAtPos(0, 15); - default : - return jjMoveNfa_0(1, 0); - } -} -private final void jjCheckNAdd(int state) -{ - if (jjrounds[state] != jjround) - { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } -} -private final void jjAddStates(int start, int end) -{ - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); -} -private final void jjCheckNAddTwoStates(int state1, int state2) -{ - jjCheckNAdd(state1); - jjCheckNAdd(state2); -} -private final void jjCheckNAddStates(int start, int end) -{ - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); -} -private final void jjCheckNAddStates(int start) -{ - jjCheckNAdd(jjnextStates[start]); - jjCheckNAdd(jjnextStates[start + 1]); -} -private final int jjMoveNfa_0(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 1: - if ((0xa3ffacfa00000000L & l) != 0L) - { - if (kind > 14) - kind = 14; - jjCheckNAdd(2); - } - else if ((0x100000200L & l) != 0L) - { - if (kind > 10) - kind = 10; - jjCheckNAdd(0); - } - break; - case 0: - if ((0x100000200L & l) == 0L) - break; - kind = 10; - jjCheckNAdd(0); - break; - case 2: - if ((0xa3ffecfa00000000L & l) == 0L) - break; - if (kind > 14) - kind = 14; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 1: - case 2: - if ((0x7fffffffc7fffffeL & l) == 0L) - break; - if (kind > 14) - kind = 14; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_2(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_2(int pos, long active0) -{ - return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_2(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_2(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_2() -{ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 22); - case 41: - return jjStopAtPos(0, 20); - default : - return jjMoveNfa_2(0, 0); - } -} -static final long[] jjbitVec0 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -private final int jjMoveNfa_2(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 23) - kind = 23; - break; - case 1: - if (kind > 21) - kind = 21; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 23) - kind = 23; - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 21) - kind = 21; - break; - case 2: - if (kind > 23) - kind = 23; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 23) - kind = 23; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 21) - kind = 21; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_4(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_4(int pos, long active0) -{ - return jjMoveNfa_4(jjStopStringLiteralDfa_4(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_4(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_4(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_4() -{ - switch(curChar) - { - case 34: - return jjStopAtPos(0, 31); - default : - return jjMoveNfa_4(0, 0); - } -} -private final int jjMoveNfa_4(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - case 2: - if ((0xfffffffbffffffffL & l) == 0L) - break; - if (kind > 30) - kind = 30; - jjCheckNAdd(2); - break; - case 1: - if (kind > 29) - kind = 29; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0xffffffffefffffffL & l) != 0L) - { - if (kind > 30) - kind = 30; - jjCheckNAdd(2); - } - else if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 29) - kind = 29; - break; - case 2: - if ((0xffffffffefffffffL & l) == 0L) - break; - if (kind > 30) - kind = 30; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - case 2: - if ((jjbitVec0[i2] & l2) == 0L) - break; - if (kind > 30) - kind = 30; - jjCheckNAdd(2); - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 29) - kind = 29; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_3(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_3(int pos, long active0) -{ - return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_3(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_3(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_3() -{ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 25); - case 41: - return jjStopAtPos(0, 26); - default : - return jjMoveNfa_3(0, 0); - } -} -private final int jjMoveNfa_3(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 27) - kind = 27; - break; - case 1: - if (kind > 24) - kind = 24; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 27) - kind = 27; - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 24) - kind = 24; - break; - case 2: - if (kind > 27) - kind = 27; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 27) - kind = 27; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 24) - kind = 24; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_1(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_1(int pos, long active0) -{ - return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_1(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_1(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_1() -{ - switch(curChar) - { - case 93: - return jjStopAtPos(0, 18); - default : - return jjMoveNfa_1(0, 0); - } -} -private final int jjMoveNfa_1(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 17) - kind = 17; - break; - case 1: - if (kind > 16) - kind = 16; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0xffffffffc7ffffffL & l) != 0L) - { - if (kind > 17) - kind = 17; - } - else if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 16) - kind = 16; - break; - case 2: - if ((0xffffffffc7ffffffL & l) != 0L && kind > 17) - kind = 17; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 17) - kind = 17; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 16) - kind = 16; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -static final int[] jjnextStates = { -}; -public static final String[] jjstrLiteralImages = { -"", "\15", "\12", "\54", "\72", "\73", "\74", "\76", "\100", "\56", null, null, -null, null, null, null, null, null, null, null, null, null, null, null, null, null, -null, null, null, null, null, null, null, null, }; -public static final String[] lexStateNames = { - "DEFAULT", - "INDOMAINLITERAL", - "INCOMMENT", - "NESTED_COMMENT", - "INQUOTEDSTRING", -}; -public static final int[] jjnewLexState = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, 2, 0, -1, 3, -1, -1, - -1, -1, -1, 4, -1, -1, 0, -1, -1, -}; -static final long[] jjtoToken = { - 0x800443ffL, -}; -static final long[] jjtoSkip = { - 0x100400L, -}; -static final long[] jjtoSpecial = { - 0x400L, -}; -static final long[] jjtoMore = { - 0x7feb8000L, -}; -protected SimpleCharStream input_stream; -private final int[] jjrounds = new int[3]; -private final int[] jjstateSet = new int[6]; -StringBuffer image; -int jjimageLen; -int lengthOfMatch; -protected char curChar; -public AddressListParserTokenManager(SimpleCharStream stream){ - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - input_stream = stream; -} -public AddressListParserTokenManager(SimpleCharStream stream, int lexState){ - this(stream); - SwitchTo(lexState); -} -public void ReInit(SimpleCharStream stream) -{ - jjmatchedPos = jjnewStateCnt = 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); -} -private final void ReInitRounds() -{ - int i; - jjround = 0x80000001; - for (i = 3; i-- > 0;) - jjrounds[i] = 0x80000000; -} -public void ReInit(SimpleCharStream stream, int lexState) -{ - ReInit(stream); - SwitchTo(lexState); -} -public void SwitchTo(int lexState) -{ - if (lexState >= 5 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; -} - -protected Token jjFillToken() -{ - Token t = Token.newToken(jjmatchedKind); - t.kind = jjmatchedKind; - String im = jjstrLiteralImages[jjmatchedKind]; - t.image = (im == null) ? input_stream.GetImage() : im; - t.beginLine = input_stream.getBeginLine(); - t.beginColumn = input_stream.getBeginColumn(); - t.endLine = input_stream.getEndLine(); - t.endColumn = input_stream.getEndColumn(); - return t; -} - -int curLexState = 0; -int defaultLexState = 0; -int jjnewStateCnt; -int jjround; -int jjmatchedPos; -int jjmatchedKind; - -public Token getNextToken() -{ - int kind; - Token specialToken = null; - Token matchedToken; - int curPos = 0; - - EOFLoop : - for (;;) - { - try - { - curChar = input_stream.BeginToken(); - } - catch(java.io.IOException e) - { - jjmatchedKind = 0; - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - return matchedToken; - } - image = null; - jjimageLen = 0; - - for (;;) - { - switch(curLexState) - { - case 0: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - break; - case 1: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - break; - case 2: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - break; - case 3: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_3(); - break; - case 4: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_4(); - break; - } - if (jjmatchedKind != 0x7fffffff) - { - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - TokenLexicalActions(matchedToken); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - } - else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - if (specialToken == null) - specialToken = matchedToken; - else - { - matchedToken.specialToken = specialToken; - specialToken = (specialToken.next = matchedToken); - } - } - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - MoreLexicalActions(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - curPos = 0; - jjmatchedKind = 0x7fffffff; - try { - curChar = input_stream.readChar(); - continue; - } - catch (java.io.IOException e1) { } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { input_stream.readChar(); input_stream.backup(1); } - catch (java.io.IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } - else - error_column++; - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } - } -} - -void MoreLexicalActions() -{ - jjimageLen += (lengthOfMatch = jjmatchedPos + 1); - switch(jjmatchedKind) - { - case 16 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 21 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 22 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - commentNest = 1; - break; - case 24 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 25 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - ++commentNest; - break; - case 26 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); - break; - case 28 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 1); - break; - case 29 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - default : - break; - } -} -void TokenLexicalActions(Token matchedToken) -{ - switch(jjmatchedKind) - { - case 18 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1))); - matchedToken.image = image.toString(); - break; - case 31 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1))); - matchedToken.image = image.substring(0, image.length() - 1); - break; - default : - break; - } -} -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java b/apache/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java deleted file mode 100644 index 5987f19d82e0469e9b56c50857e033a9c4bade01..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java +++ /dev/null @@ -1,35 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParserTreeConstants.java */ - -package org.apache.james.mime4j.field.address.parser; - -public interface AddressListParserTreeConstants -{ - public int JJTVOID = 0; - public int JJTADDRESS_LIST = 1; - public int JJTADDRESS = 2; - public int JJTMAILBOX = 3; - public int JJTNAME_ADDR = 4; - public int JJTGROUP_BODY = 5; - public int JJTANGLE_ADDR = 6; - public int JJTROUTE = 7; - public int JJTPHRASE = 8; - public int JJTADDR_SPEC = 9; - public int JJTLOCAL_PART = 10; - public int JJTDOMAIN = 11; - - - public String[] jjtNodeName = { - "void", - "address_list", - "address", - "mailbox", - "name_addr", - "group_body", - "angle_addr", - "route", - "phrase", - "addr_spec", - "local_part", - "domain", - }; -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java b/apache/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java deleted file mode 100644 index 8ec2fe7d2e42c75b1828523e108c15a94cb3b03d..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java +++ /dev/null @@ -1,19 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParserVisitor.java */ - -package org.apache.james.mime4j.field.address.parser; - -public interface AddressListParserVisitor -{ - public Object visit(SimpleNode node, Object data); - public Object visit(ASTaddress_list node, Object data); - public Object visit(ASTaddress node, Object data); - public Object visit(ASTmailbox node, Object data); - public Object visit(ASTname_addr node, Object data); - public Object visit(ASTgroup_body node, Object data); - public Object visit(ASTangle_addr node, Object data); - public Object visit(ASTroute node, Object data); - public Object visit(ASTphrase node, Object data); - public Object visit(ASTaddr_spec node, Object data); - public Object visit(ASTlocal_part node, Object data); - public Object visit(ASTdomain node, Object data); -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/BaseNode.java b/apache/org/apache/james/mime4j/field/address/parser/BaseNode.java deleted file mode 100644 index 7809746165e6b8242edf4cb54814e8f7eb725ab9..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/BaseNode.java +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.address.parser; - -import org.apache.james.mime4j.field.address.parser.Node; -import org.apache.james.mime4j.field.address.parser.Token; - -public abstract class BaseNode implements Node { - - public Token firstToken; - public Token lastToken; - -} \ No newline at end of file diff --git a/apache/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java b/apache/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java deleted file mode 100644 index 08b5c5beff247bd2a1ed8de5737592cf61e1ac56..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java +++ /dev/null @@ -1,123 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/JJTAddressListParserState.java */ - -package org.apache.james.mime4j.field.address.parser; - -class JJTAddressListParserState { - private java.util.Stack nodes; - private java.util.Stack marks; - - private int sp; // number of nodes on stack - private int mk; // current mark - private boolean node_created; - - JJTAddressListParserState() { - nodes = new java.util.Stack(); - marks = new java.util.Stack(); - sp = 0; - mk = 0; - } - - /* Determines whether the current node was actually closed and - pushed. This should only be called in the final user action of a - node scope. */ - boolean nodeCreated() { - return node_created; - } - - /* Call this to reinitialize the node stack. It is called - automatically by the parser's ReInit() method. */ - void reset() { - nodes.removeAllElements(); - marks.removeAllElements(); - sp = 0; - mk = 0; - } - - /* Returns the root node of the AST. It only makes sense to call - this after a successful parse. */ - Node rootNode() { - return nodes.elementAt(0); - } - - /* Pushes a node on to the stack. */ - void pushNode(Node n) { - nodes.push(n); - ++sp; - } - - /* Returns the node on the top of the stack, and remove it from the - stack. */ - Node popNode() { - if (--sp < mk) { - mk = marks.pop().intValue(); - } - return nodes.pop(); - } - - /* Returns the node currently on the top of the stack. */ - Node peekNode() { - return nodes.peek(); - } - - /* Returns the number of children on the stack in the current node - scope. */ - int nodeArity() { - return sp - mk; - } - - - void clearNodeScope(Node n) { - while (sp > mk) { - popNode(); - } - mk = marks.pop().intValue(); - } - - - void openNodeScope(Node n) { - marks.push(new Integer(mk)); - mk = sp; - n.jjtOpen(); - } - - - /* A definite node is constructed from a specified number of - children. That number of nodes are popped from the stack and - made the children of the definite node. Then the definite node - is pushed on to the stack. */ - void closeNodeScope(Node n, int num) { - mk = marks.pop().intValue(); - while (num-- > 0) { - Node c = popNode(); - c.jjtSetParent(n); - n.jjtAddChild(c, num); - } - n.jjtClose(); - pushNode(n); - node_created = true; - } - - - /* A conditional node is constructed if its condition is true. All - the nodes that have been pushed since the node was opened are - made children of the the conditional node, which is then pushed - on to the stack. If the condition is false the node is not - constructed and they are left on the stack. */ - void closeNodeScope(Node n, boolean condition) { - if (condition) { - int a = nodeArity(); - mk = marks.pop().intValue(); - while (a-- > 0) { - Node c = popNode(); - c.jjtSetParent(n); - n.jjtAddChild(c, a); - } - n.jjtClose(); - pushNode(n); - node_created = true; - } else { - mk = marks.pop().intValue(); - node_created = false; - } - } -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/Node.java b/apache/org/apache/james/mime4j/field/address/parser/Node.java deleted file mode 100644 index 158892016f5a1a476fb925c5fdb3d8b40a10aa86..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/Node.java +++ /dev/null @@ -1,37 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. Node.java */ - -package org.apache.james.mime4j.field.address.parser; - -/* All AST nodes must implement this interface. It provides basic - machinery for constructing the parent and child relationships - between nodes. */ - -public interface Node { - - /** This method is called after the node has been made the current - node. It indicates that child nodes can now be added to it. */ - public void jjtOpen(); - - /** This method is called after all the child nodes have been - added. */ - public void jjtClose(); - - /** This pair of methods are used to inform the node of its - parent. */ - public void jjtSetParent(Node n); - public Node jjtGetParent(); - - /** This method tells the node to add its argument to the node's - list of children. */ - public void jjtAddChild(Node n, int i); - - /** This method returns a child node. The children are numbered - from zero, left to right. */ - public Node jjtGetChild(int i); - - /** Return the number of children the node has. */ - public int jjtGetNumChildren(); - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data); -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/ParseException.java b/apache/org/apache/james/mime4j/field/address/parser/ParseException.java deleted file mode 100644 index e20146fb66250971a91cf62279966cd3a9f48a23..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/ParseException.java +++ /dev/null @@ -1,207 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -/** - * This exception is thrown when parse errors are encountered. - * You can explicitly create objects of this exception type by - * calling the method generateParseException in the generated - * parser. - * - * You can modify this class to customize your error reporting - * mechanisms so long as you retain the public fields. - */ -public class ParseException extends Exception { - - /** - * This constructor is used by the method "generateParseException" - * in the generated parser. Calling this constructor generates - * a new object of this type with the fields "currentToken", - * "expectedTokenSequences", and "tokenImage" set. The boolean - * flag "specialConstructor" is also set to true to indicate that - * this constructor was used to create this object. - * This constructor calls its super class with the empty string - * to force the "toString" method of parent class "Throwable" to - * print the error message in the form: - * ParseException: - */ - public ParseException(Token currentTokenVal, - int[][] expectedTokenSequencesVal, - String[] tokenImageVal - ) - { - super(""); - specialConstructor = true; - currentToken = currentTokenVal; - expectedTokenSequences = expectedTokenSequencesVal; - tokenImage = tokenImageVal; - } - - /** - * The following constructors are for use by you for whatever - * purpose you can think of. Constructing the exception in this - * manner makes the exception behave in the normal way - i.e., as - * documented in the class "Throwable". The fields "errorToken", - * "expectedTokenSequences", and "tokenImage" do not contain - * relevant information. The JavaCC generated code does not use - * these constructors. - */ - - public ParseException() { - super(); - specialConstructor = false; - } - - public ParseException(String message) { - super(message); - specialConstructor = false; - } - - /** - * This variable determines which constructor was used to create - * this object and thereby affects the semantics of the - * "getMessage" method (see below). - */ - protected boolean specialConstructor; - - /** - * This is the last token that has been consumed successfully. If - * this object has been created due to a parse error, the token - * followng this token will (therefore) be the first error token. - */ - public Token currentToken; - - /** - * Each entry in this array is an array of integers. Each array - * of integers represents a sequence of tokens (by their ordinal - * values) that is expected at this point of the parse. - */ - public int[][] expectedTokenSequences; - - /** - * This is a reference to the "tokenImage" array of the generated - * parser within which the parse error occurred. This array is - * defined in the generated ...Constants interface. - */ - public String[] tokenImage; - - /** - * This method has the standard behavior when this object has been - * created using the standard constructors. Otherwise, it uses - * "currentToken" and "expectedTokenSequences" to generate a parse - * error message and returns it. If this object has been created - * due to a parse error, and you do not catch it (it gets thrown - * from the parser), then this method is called during the printing - * of the final stack trace, and hence the correct error message - * gets displayed. - */ - public String getMessage() { - if (!specialConstructor) { - return super.getMessage(); - } - StringBuffer expected = new StringBuffer(); - int maxSize = 0; - for (int i = 0; i < expectedTokenSequences.length; i++) { - if (maxSize < expectedTokenSequences[i].length) { - maxSize = expectedTokenSequences[i].length; - } - for (int j = 0; j < expectedTokenSequences[i].length; j++) { - expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" "); - } - if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { - expected.append("..."); - } - expected.append(eol).append(" "); - } - String retval = "Encountered \""; - Token tok = currentToken.next; - for (int i = 0; i < maxSize; i++) { - if (i != 0) retval += " "; - if (tok.kind == 0) { - retval += tokenImage[0]; - break; - } - retval += add_escapes(tok.image); - tok = tok.next; - } - retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; - retval += "." + eol; - if (expectedTokenSequences.length == 1) { - retval += "Was expecting:" + eol + " "; - } else { - retval += "Was expecting one of:" + eol + " "; - } - retval += expected.toString(); - return retval; - } - - /** - * The end of line string for this machine. - */ - protected String eol = System.getProperty("line.separator", "\n"); - - /** - * Used to convert raw characters to their escaped version - * when these raw version cannot be used as part of an ASCII - * string literal. - */ - protected String add_escapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case 0 : - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java b/apache/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java deleted file mode 100644 index c9ba0b4444d839807db58a4b656e92f3c02ce312..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/SimpleCharStream.java +++ /dev/null @@ -1,454 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -/** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (without unicode processing). - */ - -public class SimpleCharStream -{ - public static final boolean staticFlag = false; - int bufsize; - int available; - int tokenBegin; - public int bufpos = -1; - protected int bufline[]; - protected int bufcolumn[]; - - protected int column = 0; - protected int line = 1; - - protected boolean prevCharIsCR = false; - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] buffer; - protected int maxNextCharInd = 0; - protected int inBuf = 0; - protected int tabSize = 8; - - protected void setTabSize(int i) { tabSize = i; } - protected int getTabSize(int i) { return tabSize; } - - - protected void ExpandBuff(boolean wrapAround) - { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try - { - if (wrapAround) - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, - bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos += (bufsize - tokenBegin)); - } - else - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos -= tokenBegin); - } - } - catch (Throwable t) - { - throw new Error(t.getMessage()); - } - - - bufsize += 2048; - available = bufsize; - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException - { - if (maxNextCharInd == available) - { - if (available == bufsize) - { - if (tokenBegin > 2048) - { - bufpos = maxNextCharInd = 0; - available = tokenBegin; - } - else if (tokenBegin < 0) - bufpos = maxNextCharInd = 0; - else - ExpandBuff(false); - } - else if (available > tokenBegin) - available = bufsize; - else if ((tokenBegin - available) < 2048) - ExpandBuff(true); - else - available = tokenBegin; - } - - int i; - try { - if ((i = inputStream.read(buffer, maxNextCharInd, - available - maxNextCharInd)) == -1) - { - inputStream.close(); - throw new java.io.IOException(); - } - else - maxNextCharInd += i; - return; - } - catch(java.io.IOException e) { - --bufpos; - backup(0); - if (tokenBegin == -1) - tokenBegin = bufpos; - throw e; - } - } - - public char BeginToken() throws java.io.IOException - { - tokenBegin = -1; - char c = readChar(); - tokenBegin = bufpos; - - return c; - } - - protected void UpdateLineColumn(char c) - { - column++; - - if (prevCharIsLF) - { - prevCharIsLF = false; - line += (column = 1); - } - else if (prevCharIsCR) - { - prevCharIsCR = false; - if (c == '\n') - { - prevCharIsLF = true; - } - else - line += (column = 1); - } - - switch (c) - { - case '\r' : - prevCharIsCR = true; - break; - case '\n' : - prevCharIsLF = true; - break; - case '\t' : - column--; - column += (tabSize - (column % tabSize)); - break; - default : - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - - public char readChar() throws java.io.IOException - { - if (inBuf > 0) - { - --inBuf; - - if (++bufpos == bufsize) - bufpos = 0; - - return buffer[bufpos]; - } - - if (++bufpos >= maxNextCharInd) - FillBuff(); - - char c = buffer[bufpos]; - - UpdateLineColumn(c); - return (c); - } - - /** - * @deprecated - * @see #getEndColumn - */ - @Deprecated - public int getColumn() { - return bufcolumn[bufpos]; - } - - /** - * @deprecated - * @see #getEndLine - */ - @Deprecated - public int getLine() { - return bufline[bufpos]; - } - - public int getEndColumn() { - return bufcolumn[bufpos]; - } - - public int getEndLine() { - return bufline[bufpos]; - } - - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - - public int getBeginLine() { - return bufline[tokenBegin]; - } - - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) - bufpos += bufsize; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.Reader dstream) - { - this(dstream, 1, 1, 4096); - } - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) - { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - bufpos = -1; - } - - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - - public void ReInit(java.io.Reader dstream) - { - ReInit(dstream, 1, 1, 4096); - } - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, 1, 1, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream) - { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream) - { - ReInit(dstream, 1, 1, 4096); - } - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - public String GetImage() - { - if (bufpos >= tokenBegin) - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - else - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - - public char[] GetSuffix(int len) - { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - else - { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - public void Done() - { - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - */ - public void adjustBeginLineColumn(int newLine, int newCol) - { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) - { - len = bufpos - tokenBegin + inBuf + 1; - } - else - { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k = 0; - int nextColDiff = 0, columnDiff = 0; - - while (i < len && - bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) - { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) - { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) - { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) - bufline[j] = newLine++; - else - bufline[j] = newLine; - } - } - - line = bufline[j]; - column = bufcolumn[j]; - } - -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/SimpleNode.java b/apache/org/apache/james/mime4j/field/address/parser/SimpleNode.java deleted file mode 100644 index 9bf537e60db717738b489e48af35d09ac4193051..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/SimpleNode.java +++ /dev/null @@ -1,87 +0,0 @@ -/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ - -package org.apache.james.mime4j.field.address.parser; - -public class SimpleNode extends org.apache.james.mime4j.field.address.parser.BaseNode implements Node { - protected Node parent; - protected Node[] children; - protected int id; - protected AddressListParser parser; - - public SimpleNode(int i) { - id = i; - } - - public SimpleNode(AddressListParser p, int i) { - this(i); - parser = p; - } - - public void jjtOpen() { - } - - public void jjtClose() { - } - - public void jjtSetParent(Node n) { parent = n; } - public Node jjtGetParent() { return parent; } - - public void jjtAddChild(Node n, int i) { - if (children == null) { - children = new Node[i + 1]; - } else if (i >= children.length) { - Node c[] = new Node[i + 1]; - System.arraycopy(children, 0, c, 0, children.length); - children = c; - } - children[i] = n; - } - - public Node jjtGetChild(int i) { - return children[i]; - } - - public int jjtGetNumChildren() { - return (children == null) ? 0 : children.length; - } - - /** Accept the visitor. **/ - public Object jjtAccept(AddressListParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } - - /** Accept the visitor. **/ - public Object childrenAccept(AddressListParserVisitor visitor, Object data) { - if (children != null) { - for (int i = 0; i < children.length; ++i) { - children[i].jjtAccept(visitor, data); - } - } - return data; - } - - /* You can override these two methods in subclasses of SimpleNode to - customize the way the node appears when the tree is dumped. If - your output uses more than one line you should override - toString(String), otherwise overriding toString() is probably all - you need to do. */ - - public String toString() { return AddressListParserTreeConstants.jjtNodeName[id]; } - public String toString(String prefix) { return prefix + toString(); } - - /* Override this method if you want to customize how the node dumps - out its children. */ - - public void dump(String prefix) { - System.out.println(toString(prefix)); - if (children != null) { - for (int i = 0; i < children.length; ++i) { - SimpleNode n = (SimpleNode)children[i]; - if (n != null) { - n.dump(prefix + " "); - } - } - } - } -} - diff --git a/apache/org/apache/james/mime4j/field/address/parser/Token.java b/apache/org/apache/james/mime4j/field/address/parser/Token.java deleted file mode 100644 index 2382e8e92c862c00c50d7cb820d2febdbfdc06e2..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/Token.java +++ /dev/null @@ -1,96 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -/** - * Describes the input token stream. - */ - -public class Token { - - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** - * beginLine and beginColumn describe the position of the first character - * of this token; endLine and endColumn describe the position of the - * last character of this token. - */ - public int beginLine, beginColumn, endLine, endColumn; - - /** - * The string image of the token. - */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** - * Returns the image. - */ - public String toString() - { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simlpy add something like : - * - * case MyParserConstants.ID : return new IDToken(); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use it in your lexical actions. - */ - public static final Token newToken(int ofKind) - { - switch(ofKind) - { - default : return new Token(); - } - } - -} diff --git a/apache/org/apache/james/mime4j/field/address/parser/TokenMgrError.java b/apache/org/apache/james/mime4j/field/address/parser/TokenMgrError.java deleted file mode 100644 index 0299c8523e44bf6566d86fb46c446682610f5259..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/address/parser/TokenMgrError.java +++ /dev/null @@ -1,148 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.address.parser; - -public class TokenMgrError extends Error -{ - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** - * Lexical error occured. - */ - static final int LEXICAL_ERROR = 0; - - /** - * An attempt wass made to create a second instance of a static token manager. - */ - static final int STATIC_LEXER_ERROR = 1; - - /** - * Tried to change to an invalid lexical state. - */ - static final int INVALID_LEXICAL_STATE = 2; - - /** - * Detected (and bailed out of) an infinite loop in the token manager. - */ - static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - /** - * Replaces unprintable characters by their espaced (or unicode escaped) - * equivalents in the given string - */ - protected static final String addEscapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case 0 : - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - - /** - * Returns a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - * Parameters : - * EOFSeen : indicates if EOF caused the lexicl error - * curLexState : lexical state in which this error occured - * errorLine : line number when the error occured - * errorColumn : column number when the error occured - * errorAfter : prefix that was seen before this error occured - * curchar : the offending character - * Note: You can customize the lexical error message by modifying this method. - */ - protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { - return("Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""); - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - public TokenMgrError() { - } - - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { - this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } -} diff --git a/apache/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java b/apache/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java deleted file mode 100644 index cacf3af21c8c4a38bb252fb66bb003fb08935650..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParser.java +++ /dev/null @@ -1,268 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. ContentTypeParser.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.contenttype.parser; - -import java.util.ArrayList; -import java.util.Vector; - -public class ContentTypeParser implements ContentTypeParserConstants { - - private String type; - private String subtype; - private ArrayList paramNames = new ArrayList(); - private ArrayList paramValues = new ArrayList(); - - public String getType() { return type; } - public String getSubType() { return subtype; } - public ArrayList getParamNames() { return paramNames; } - public ArrayList getParamValues() { return paramValues; } - - public static void main(String args[]) throws ParseException { - while (true) { - try { - ContentTypeParser parser = new ContentTypeParser(System.in); - parser.parseLine(); - } catch (Exception x) { - x.printStackTrace(); - return; - } - } - } - - final public void parseLine() throws ParseException { - parse(); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 1: - jj_consume_token(1); - break; - default: - jj_la1[0] = jj_gen; - ; - } - jj_consume_token(2); - } - - final public void parseAll() throws ParseException { - parse(); - jj_consume_token(0); - } - - final public void parse() throws ParseException { - Token type; - Token subtype; - type = jj_consume_token(ATOKEN); - jj_consume_token(3); - subtype = jj_consume_token(ATOKEN); - this.type = type.image; - this.subtype = subtype.image; - label_1: - while (true) { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 4: - ; - break; - default: - jj_la1[1] = jj_gen; - break label_1; - } - jj_consume_token(4); - parameter(); - } - } - - final public void parameter() throws ParseException { - Token attrib; - String val; - attrib = jj_consume_token(ATOKEN); - jj_consume_token(5); - val = value(); - paramNames.add(attrib.image); - paramValues.add(val); - } - - final public String value() throws ParseException { - Token t; - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case ATOKEN: - t = jj_consume_token(ATOKEN); - break; - case QUOTEDSTRING: - t = jj_consume_token(QUOTEDSTRING); - break; - default: - jj_la1[2] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - {if (true) return t.image;} - throw new Error("Missing return statement in function"); - } - - public ContentTypeParserTokenManager token_source; - SimpleCharStream jj_input_stream; - public Token token, jj_nt; - private int jj_ntk; - private int jj_gen; - final private int[] jj_la1 = new int[3]; - static private int[] jj_la1_0; - static { - jj_la1_0(); - } - private static void jj_la1_0() { - jj_la1_0 = new int[] {0x2,0x10,0x280000,}; - } - - public ContentTypeParser(java.io.InputStream stream) { - this(stream, null); - } - public ContentTypeParser(java.io.InputStream stream, String encoding) { - try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source = new ContentTypeParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 3; i++) jj_la1[i] = -1; - } - - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - public void ReInit(java.io.InputStream stream, String encoding) { - try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 3; i++) jj_la1[i] = -1; - } - - public ContentTypeParser(java.io.Reader stream) { - jj_input_stream = new SimpleCharStream(stream, 1, 1); - token_source = new ContentTypeParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 3; i++) jj_la1[i] = -1; - } - - public void ReInit(java.io.Reader stream) { - jj_input_stream.ReInit(stream, 1, 1); - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 3; i++) jj_la1[i] = -1; - } - - public ContentTypeParser(ContentTypeParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 3; i++) jj_la1[i] = -1; - } - - public void ReInit(ContentTypeParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 3; i++) jj_la1[i] = -1; - } - - final private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - if (token.kind == kind) { - jj_gen++; - return token; - } - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - final public Token getNextToken() { - if (token.next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - jj_gen++; - return token; - } - - final public Token getToken(int index) { - Token t = token; - for (int i = 0; i < index; i++) { - if (t.next != null) t = t.next; - else t = t.next = token_source.getNextToken(); - } - return t; - } - - final private int jj_ntk() { - if ((jj_nt=token.next) == null) - return (jj_ntk = (token.next=token_source.getNextToken()).kind); - else - return (jj_ntk = jj_nt.kind); - } - - private Vector jj_expentries = new Vector(); - private int[] jj_expentry; - private int jj_kind = -1; - - public ParseException generateParseException() { - jj_expentries.removeAllElements(); - boolean[] la1tokens = new boolean[24]; - for (int i = 0; i < 24; i++) { - la1tokens[i] = false; - } - if (jj_kind >= 0) { - la1tokens[jj_kind] = true; - jj_kind = -1; - } - for (int i = 0; i < 3; i++) { - if (jj_la1[i] == jj_gen) { - for (int j = 0; j < 32; j++) { - if ((jj_la1_0[i] & (1<", - "\"\\r\"", - "\"\\n\"", - "\"/\"", - "\";\"", - "\"=\"", - "", - "\"(\"", - "\")\"", - "", - "\"(\"", - "", - "", - "\"(\"", - "\")\"", - "", - "\"\\\"\"", - "", - "", - "\"\\\"\"", - "", - "", - "", - "", - }; - -} diff --git a/apache/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java b/apache/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java deleted file mode 100644 index 25b7abafa0173b4f65991f797499960d08222131..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/contenttype/parser/ContentTypeParserTokenManager.java +++ /dev/null @@ -1,877 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. ContentTypeParserTokenManager.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.contenttype.parser; -import java.util.ArrayList; - -public class ContentTypeParserTokenManager implements ContentTypeParserConstants -{ - // Keeps track of how many levels of comment nesting - // we've encountered. This is only used when the 2nd - // level is reached, for example ((this)), not (this). - // This is because the outermost level must be treated - // specially anyway, because the outermost ")" has a - // different token type than inner ")" instances. - static int commentNest; - public java.io.PrintStream debugStream = System.out; - public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } -private final int jjStopStringLiteralDfa_0(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_0(int pos, long active0) -{ - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); -} -private final int jjStopAtPos(int pos, int kind) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; -} -private final int jjStartNfaWithStates_0(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_0(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_0() -{ - switch(curChar) - { - case 10: - return jjStartNfaWithStates_0(0, 2, 2); - case 13: - return jjStartNfaWithStates_0(0, 1, 2); - case 34: - return jjStopAtPos(0, 16); - case 40: - return jjStopAtPos(0, 7); - case 47: - return jjStopAtPos(0, 3); - case 59: - return jjStopAtPos(0, 4); - case 61: - return jjStopAtPos(0, 5); - default : - return jjMoveNfa_0(3, 0); - } -} -private final void jjCheckNAdd(int state) -{ - if (jjrounds[state] != jjround) - { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } -} -private final void jjAddStates(int start, int end) -{ - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); -} -private final void jjCheckNAddTwoStates(int state1, int state2) -{ - jjCheckNAdd(state1); - jjCheckNAdd(state2); -} -private final void jjCheckNAddStates(int start, int end) -{ - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); -} -private final void jjCheckNAddStates(int start) -{ - jjCheckNAdd(jjnextStates[start]); - jjCheckNAdd(jjnextStates[start + 1]); -} -static final long[] jjbitVec0 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -private final int jjMoveNfa_0(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 3: - if ((0x3ff6cfafffffdffL & l) != 0L) - { - if (kind > 21) - kind = 21; - jjCheckNAdd(2); - } - else if ((0x100000200L & l) != 0L) - { - if (kind > 6) - kind = 6; - jjCheckNAdd(0); - } - if ((0x3ff000000000000L & l) != 0L) - { - if (kind > 20) - kind = 20; - jjCheckNAdd(1); - } - break; - case 0: - if ((0x100000200L & l) == 0L) - break; - kind = 6; - jjCheckNAdd(0); - break; - case 1: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 20) - kind = 20; - jjCheckNAdd(1); - break; - case 2: - if ((0x3ff6cfafffffdffL & l) == 0L) - break; - if (kind > 21) - kind = 21; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 3: - case 2: - if ((0xffffffffc7fffffeL & l) == 0L) - break; - kind = 21; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 3: - case 2: - if ((jjbitVec0[i2] & l2) == 0L) - break; - if (kind > 21) - kind = 21; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_1(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_1(int pos, long active0) -{ - return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_1(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_1(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_1() -{ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 10); - case 41: - return jjStopAtPos(0, 8); - default : - return jjMoveNfa_1(0, 0); - } -} -private final int jjMoveNfa_1(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 11) - kind = 11; - break; - case 1: - if (kind > 9) - kind = 9; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 11) - kind = 11; - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 9) - kind = 9; - break; - case 2: - if (kind > 11) - kind = 11; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 11) - kind = 11; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 9) - kind = 9; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_3(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_3(int pos, long active0) -{ - return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_3(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_3(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_3() -{ - switch(curChar) - { - case 34: - return jjStopAtPos(0, 19); - default : - return jjMoveNfa_3(0, 0); - } -} -private final int jjMoveNfa_3(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - case 2: - if ((0xfffffffbffffffffL & l) == 0L) - break; - if (kind > 18) - kind = 18; - jjCheckNAdd(2); - break; - case 1: - if (kind > 17) - kind = 17; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0xffffffffefffffffL & l) != 0L) - { - if (kind > 18) - kind = 18; - jjCheckNAdd(2); - } - else if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 17) - kind = 17; - break; - case 2: - if ((0xffffffffefffffffL & l) == 0L) - break; - if (kind > 18) - kind = 18; - jjCheckNAdd(2); - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - case 2: - if ((jjbitVec0[i2] & l2) == 0L) - break; - if (kind > 18) - kind = 18; - jjCheckNAdd(2); - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 17) - kind = 17; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_2(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_2(int pos, long active0) -{ - return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_2(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_2(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_2() -{ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 13); - case 41: - return jjStopAtPos(0, 14); - default : - return jjMoveNfa_2(0, 0); - } -} -private final int jjMoveNfa_2(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 15) - kind = 15; - break; - case 1: - if (kind > 12) - kind = 12; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 15) - kind = 15; - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 12) - kind = 12; - break; - case 2: - if (kind > 15) - kind = 15; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 15) - kind = 15; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 12) - kind = 12; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -static final int[] jjnextStates = { -}; -public static final String[] jjstrLiteralImages = { -"", "\15", "\12", "\57", "\73", "\75", null, null, null, null, null, null, -null, null, null, null, null, null, null, null, null, null, null, null, }; -public static final String[] lexStateNames = { - "DEFAULT", - "INCOMMENT", - "NESTED_COMMENT", - "INQUOTEDSTRING", -}; -public static final int[] jjnewLexState = { - -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, -1, -1, -1, -}; -static final long[] jjtoToken = { - 0x38003fL, -}; -static final long[] jjtoSkip = { - 0x140L, -}; -static final long[] jjtoSpecial = { - 0x40L, -}; -static final long[] jjtoMore = { - 0x7fe80L, -}; -protected SimpleCharStream input_stream; -private final int[] jjrounds = new int[3]; -private final int[] jjstateSet = new int[6]; -StringBuffer image; -int jjimageLen; -int lengthOfMatch; -protected char curChar; -public ContentTypeParserTokenManager(SimpleCharStream stream){ - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - input_stream = stream; -} -public ContentTypeParserTokenManager(SimpleCharStream stream, int lexState){ - this(stream); - SwitchTo(lexState); -} -public void ReInit(SimpleCharStream stream) -{ - jjmatchedPos = jjnewStateCnt = 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); -} -private final void ReInitRounds() -{ - int i; - jjround = 0x80000001; - for (i = 3; i-- > 0;) - jjrounds[i] = 0x80000000; -} -public void ReInit(SimpleCharStream stream, int lexState) -{ - ReInit(stream); - SwitchTo(lexState); -} -public void SwitchTo(int lexState) -{ - if (lexState >= 4 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; -} - -protected Token jjFillToken() -{ - Token t = Token.newToken(jjmatchedKind); - t.kind = jjmatchedKind; - String im = jjstrLiteralImages[jjmatchedKind]; - t.image = (im == null) ? input_stream.GetImage() : im; - t.beginLine = input_stream.getBeginLine(); - t.beginColumn = input_stream.getBeginColumn(); - t.endLine = input_stream.getEndLine(); - t.endColumn = input_stream.getEndColumn(); - return t; -} - -int curLexState = 0; -int defaultLexState = 0; -int jjnewStateCnt; -int jjround; -int jjmatchedPos; -int jjmatchedKind; - -public Token getNextToken() -{ - int kind; - Token specialToken = null; - Token matchedToken; - int curPos = 0; - - EOFLoop : - for (;;) - { - try - { - curChar = input_stream.BeginToken(); - } - catch(java.io.IOException e) - { - jjmatchedKind = 0; - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - return matchedToken; - } - image = null; - jjimageLen = 0; - - for (;;) - { - switch(curLexState) - { - case 0: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - break; - case 1: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - break; - case 2: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - break; - case 3: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_3(); - break; - } - if (jjmatchedKind != 0x7fffffff) - { - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - TokenLexicalActions(matchedToken); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - } - else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - if (specialToken == null) - specialToken = matchedToken; - else - { - matchedToken.specialToken = specialToken; - specialToken = (specialToken.next = matchedToken); - } - } - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - MoreLexicalActions(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - curPos = 0; - jjmatchedKind = 0x7fffffff; - try { - curChar = input_stream.readChar(); - continue; - } - catch (java.io.IOException e1) { } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { input_stream.readChar(); input_stream.backup(1); } - catch (java.io.IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } - else - error_column++; - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } - } -} - -void MoreLexicalActions() -{ - jjimageLen += (lengthOfMatch = jjmatchedPos + 1); - switch(jjmatchedKind) - { - case 9 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 10 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - commentNest = 1; - break; - case 12 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 13 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - ++commentNest; - break; - case 14 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); - break; - case 16 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 1); - break; - case 17 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - default : - break; - } -} -void TokenLexicalActions(Token matchedToken) -{ - switch(jjmatchedKind) - { - case 19 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1))); - matchedToken.image = image.substring(0, image.length() - 1); - break; - default : - break; - } -} -} diff --git a/apache/org/apache/james/mime4j/field/contenttype/parser/ParseException.java b/apache/org/apache/james/mime4j/field/contenttype/parser/ParseException.java deleted file mode 100644 index d9b69b25c72681a3a6c9afaad1266ffa64e63d6b..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/contenttype/parser/ParseException.java +++ /dev/null @@ -1,207 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.contenttype.parser; - -/** - * This exception is thrown when parse errors are encountered. - * You can explicitly create objects of this exception type by - * calling the method generateParseException in the generated - * parser. - * - * You can modify this class to customize your error reporting - * mechanisms so long as you retain the public fields. - */ -public class ParseException extends Exception { - - /** - * This constructor is used by the method "generateParseException" - * in the generated parser. Calling this constructor generates - * a new object of this type with the fields "currentToken", - * "expectedTokenSequences", and "tokenImage" set. The boolean - * flag "specialConstructor" is also set to true to indicate that - * this constructor was used to create this object. - * This constructor calls its super class with the empty string - * to force the "toString" method of parent class "Throwable" to - * print the error message in the form: - * ParseException: - */ - public ParseException(Token currentTokenVal, - int[][] expectedTokenSequencesVal, - String[] tokenImageVal - ) - { - super(""); - specialConstructor = true; - currentToken = currentTokenVal; - expectedTokenSequences = expectedTokenSequencesVal; - tokenImage = tokenImageVal; - } - - /** - * The following constructors are for use by you for whatever - * purpose you can think of. Constructing the exception in this - * manner makes the exception behave in the normal way - i.e., as - * documented in the class "Throwable". The fields "errorToken", - * "expectedTokenSequences", and "tokenImage" do not contain - * relevant information. The JavaCC generated code does not use - * these constructors. - */ - - public ParseException() { - super(); - specialConstructor = false; - } - - public ParseException(String message) { - super(message); - specialConstructor = false; - } - - /** - * This variable determines which constructor was used to create - * this object and thereby affects the semantics of the - * "getMessage" method (see below). - */ - protected boolean specialConstructor; - - /** - * This is the last token that has been consumed successfully. If - * this object has been created due to a parse error, the token - * followng this token will (therefore) be the first error token. - */ - public Token currentToken; - - /** - * Each entry in this array is an array of integers. Each array - * of integers represents a sequence of tokens (by their ordinal - * values) that is expected at this point of the parse. - */ - public int[][] expectedTokenSequences; - - /** - * This is a reference to the "tokenImage" array of the generated - * parser within which the parse error occurred. This array is - * defined in the generated ...Constants interface. - */ - public String[] tokenImage; - - /** - * This method has the standard behavior when this object has been - * created using the standard constructors. Otherwise, it uses - * "currentToken" and "expectedTokenSequences" to generate a parse - * error message and returns it. If this object has been created - * due to a parse error, and you do not catch it (it gets thrown - * from the parser), then this method is called during the printing - * of the final stack trace, and hence the correct error message - * gets displayed. - */ - public String getMessage() { - if (!specialConstructor) { - return super.getMessage(); - } - StringBuffer expected = new StringBuffer(); - int maxSize = 0; - for (int i = 0; i < expectedTokenSequences.length; i++) { - if (maxSize < expectedTokenSequences[i].length) { - maxSize = expectedTokenSequences[i].length; - } - for (int j = 0; j < expectedTokenSequences[i].length; j++) { - expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" "); - } - if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { - expected.append("..."); - } - expected.append(eol).append(" "); - } - String retval = "Encountered \""; - Token tok = currentToken.next; - for (int i = 0; i < maxSize; i++) { - if (i != 0) retval += " "; - if (tok.kind == 0) { - retval += tokenImage[0]; - break; - } - retval += add_escapes(tok.image); - tok = tok.next; - } - retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; - retval += "." + eol; - if (expectedTokenSequences.length == 1) { - retval += "Was expecting:" + eol + " "; - } else { - retval += "Was expecting one of:" + eol + " "; - } - retval += expected.toString(); - return retval; - } - - /** - * The end of line string for this machine. - */ - protected String eol = System.getProperty("line.separator", "\n"); - - /** - * Used to convert raw characters to their escaped version - * when these raw version cannot be used as part of an ASCII - * string literal. - */ - protected String add_escapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case 0 : - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - -} diff --git a/apache/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java b/apache/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java deleted file mode 100644 index ae035b717126055538f2910a4e7f2d8c89424a8d..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/contenttype/parser/SimpleCharStream.java +++ /dev/null @@ -1,454 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.contenttype.parser; - -/** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (without unicode processing). - */ - -public class SimpleCharStream -{ - public static final boolean staticFlag = false; - int bufsize; - int available; - int tokenBegin; - public int bufpos = -1; - protected int bufline[]; - protected int bufcolumn[]; - - protected int column = 0; - protected int line = 1; - - protected boolean prevCharIsCR = false; - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] buffer; - protected int maxNextCharInd = 0; - protected int inBuf = 0; - protected int tabSize = 8; - - protected void setTabSize(int i) { tabSize = i; } - protected int getTabSize(int i) { return tabSize; } - - - protected void ExpandBuff(boolean wrapAround) - { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try - { - if (wrapAround) - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, - bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos += (bufsize - tokenBegin)); - } - else - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos -= tokenBegin); - } - } - catch (Throwable t) - { - throw new Error(t.getMessage()); - } - - - bufsize += 2048; - available = bufsize; - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException - { - if (maxNextCharInd == available) - { - if (available == bufsize) - { - if (tokenBegin > 2048) - { - bufpos = maxNextCharInd = 0; - available = tokenBegin; - } - else if (tokenBegin < 0) - bufpos = maxNextCharInd = 0; - else - ExpandBuff(false); - } - else if (available > tokenBegin) - available = bufsize; - else if ((tokenBegin - available) < 2048) - ExpandBuff(true); - else - available = tokenBegin; - } - - int i; - try { - if ((i = inputStream.read(buffer, maxNextCharInd, - available - maxNextCharInd)) == -1) - { - inputStream.close(); - throw new java.io.IOException(); - } - else - maxNextCharInd += i; - return; - } - catch(java.io.IOException e) { - --bufpos; - backup(0); - if (tokenBegin == -1) - tokenBegin = bufpos; - throw e; - } - } - - public char BeginToken() throws java.io.IOException - { - tokenBegin = -1; - char c = readChar(); - tokenBegin = bufpos; - - return c; - } - - protected void UpdateLineColumn(char c) - { - column++; - - if (prevCharIsLF) - { - prevCharIsLF = false; - line += (column = 1); - } - else if (prevCharIsCR) - { - prevCharIsCR = false; - if (c == '\n') - { - prevCharIsLF = true; - } - else - line += (column = 1); - } - - switch (c) - { - case '\r' : - prevCharIsCR = true; - break; - case '\n' : - prevCharIsLF = true; - break; - case '\t' : - column--; - column += (tabSize - (column % tabSize)); - break; - default : - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - - public char readChar() throws java.io.IOException - { - if (inBuf > 0) - { - --inBuf; - - if (++bufpos == bufsize) - bufpos = 0; - - return buffer[bufpos]; - } - - if (++bufpos >= maxNextCharInd) - FillBuff(); - - char c = buffer[bufpos]; - - UpdateLineColumn(c); - return (c); - } - - /** - * @deprecated - * @see #getEndColumn - */ - @Deprecated - public int getColumn() { - return bufcolumn[bufpos]; - } - - /** - * @deprecated - * @see #getEndLine - */ - @Deprecated - public int getLine() { - return bufline[bufpos]; - } - - public int getEndColumn() { - return bufcolumn[bufpos]; - } - - public int getEndLine() { - return bufline[bufpos]; - } - - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - - public int getBeginLine() { - return bufline[tokenBegin]; - } - - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) - bufpos += bufsize; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.Reader dstream) - { - this(dstream, 1, 1, 4096); - } - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) - { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - bufpos = -1; - } - - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - - public void ReInit(java.io.Reader dstream) - { - ReInit(dstream, 1, 1, 4096); - } - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, 1, 1, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream) - { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream) - { - ReInit(dstream, 1, 1, 4096); - } - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - public String GetImage() - { - if (bufpos >= tokenBegin) - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - else - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - - public char[] GetSuffix(int len) - { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - else - { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - public void Done() - { - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - */ - public void adjustBeginLineColumn(int newLine, int newCol) - { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) - { - len = bufpos - tokenBegin + inBuf + 1; - } - else - { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k = 0; - int nextColDiff = 0, columnDiff = 0; - - while (i < len && - bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) - { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) - { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) - { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) - bufline[j] = newLine++; - else - bufline[j] = newLine; - } - } - - line = bufline[j]; - column = bufcolumn[j]; - } - -} diff --git a/apache/org/apache/james/mime4j/field/contenttype/parser/Token.java b/apache/org/apache/james/mime4j/field/contenttype/parser/Token.java deleted file mode 100644 index 34e65eec0b4ddc91594bb382b57edef07a53318d..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/contenttype/parser/Token.java +++ /dev/null @@ -1,96 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.contenttype.parser; - -/** - * Describes the input token stream. - */ - -public class Token { - - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** - * beginLine and beginColumn describe the position of the first character - * of this token; endLine and endColumn describe the position of the - * last character of this token. - */ - public int beginLine, beginColumn, endLine, endColumn; - - /** - * The string image of the token. - */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** - * Returns the image. - */ - public String toString() - { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simlpy add something like : - * - * case MyParserConstants.ID : return new IDToken(); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use it in your lexical actions. - */ - public static final Token newToken(int ofKind) - { - switch(ofKind) - { - default : return new Token(); - } - } - -} diff --git a/apache/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java b/apache/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java deleted file mode 100644 index ea5a7826e92367da5541a9cd2a23cd4da53a4ff9..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/contenttype/parser/TokenMgrError.java +++ /dev/null @@ -1,148 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.contenttype.parser; - -public class TokenMgrError extends Error -{ - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** - * Lexical error occured. - */ - static final int LEXICAL_ERROR = 0; - - /** - * An attempt wass made to create a second instance of a static token manager. - */ - static final int STATIC_LEXER_ERROR = 1; - - /** - * Tried to change to an invalid lexical state. - */ - static final int INVALID_LEXICAL_STATE = 2; - - /** - * Detected (and bailed out of) an infinite loop in the token manager. - */ - static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - /** - * Replaces unprintable characters by their espaced (or unicode escaped) - * equivalents in the given string - */ - protected static final String addEscapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case 0 : - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - - /** - * Returns a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - * Parameters : - * EOFSeen : indicates if EOF caused the lexicl error - * curLexState : lexical state in which this error occured - * errorLine : line number when the error occured - * errorColumn : column number when the error occured - * errorAfter : prefix that was seen before this error occured - * curchar : the offending character - * Note: You can customize the lexical error message by modifying this method. - */ - protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { - return("Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""); - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - public TokenMgrError() { - } - - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { - this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } -} diff --git a/apache/org/apache/james/mime4j/field/datetime/DateTime.java b/apache/org/apache/james/mime4j/field/datetime/DateTime.java deleted file mode 100644 index 506ff54e5d788276b8ff89855a44e1562884b491..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/DateTime.java +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.field.datetime; - -import org.apache.james.mime4j.field.datetime.parser.DateTimeParser; -import org.apache.james.mime4j.field.datetime.parser.ParseException; -import org.apache.james.mime4j.field.datetime.parser.TokenMgrError; - -import java.util.Date; -import java.util.Calendar; -import java.util.TimeZone; -import java.util.GregorianCalendar; -import java.io.StringReader; - -public class DateTime { - private final Date date; - private final int year; - private final int month; - private final int day; - private final int hour; - private final int minute; - private final int second; - private final int timeZone; - - public DateTime(String yearString, int month, int day, int hour, int minute, int second, int timeZone) { - this.year = convertToYear(yearString); - this.date = convertToDate(year, month, day, hour, minute, second, timeZone); - this.month = month; - this.day = day; - this.hour = hour; - this.minute = minute; - this.second = second; - this.timeZone = timeZone; - } - - private int convertToYear(String yearString) { - int year = Integer.parseInt(yearString); - switch (yearString.length()) { - case 1: - case 2: - if (year >= 0 && year < 50) - return 2000 + year; - else - return 1900 + year; - case 3: - return 1900 + year; - default: - return year; - } - } - - public static Date convertToDate(int year, int month, int day, int hour, int minute, int second, int timeZone) { - Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT+0")); - c.set(year, month - 1, day, hour, minute, second); - c.set(Calendar.MILLISECOND, 0); - - if (timeZone != Integer.MIN_VALUE) { - int minutes = ((timeZone / 100) * 60) + timeZone % 100; - c.add(Calendar.MINUTE, -1 * minutes); - } - - return c.getTime(); - } - - public Date getDate() { - return date; - } - - public int getYear() { - return year; - } - - public int getMonth() { - return month; - } - - public int getDay() { - return day; - } - - public int getHour() { - return hour; - } - - public int getMinute() { - return minute; - } - - public int getSecond() { - return second; - } - - public int getTimeZone() { - return timeZone; - } - - public void print() { - System.out.println(getYear() + " " + getMonth() + " " + getDay() + "; " + getHour() + " " + getMinute() + " " + getSecond() + " " + getTimeZone()); - } - - - public static DateTime parse(String dateString) throws ParseException { - try { - return new DateTimeParser(new StringReader(dateString)).parseAll(); - } - catch (TokenMgrError err) { - throw new ParseException(err.getMessage()); - } - } -} diff --git a/apache/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java b/apache/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java deleted file mode 100644 index 43edebb5c8b0dd3a09576c66d0655512dee7a804..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/parser/DateTimeParser.java +++ /dev/null @@ -1,570 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. DateTimeParser.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.datetime.parser; - -import org.apache.james.mime4j.field.datetime.DateTime; - -import java.util.Vector; - -public class DateTimeParser implements DateTimeParserConstants { - private static final boolean ignoreMilitaryZoneOffset = true; - - public static void main(String args[]) throws ParseException { - while (true) { - try { - DateTimeParser parser = new DateTimeParser(System.in); - parser.parseLine(); - } catch (Exception x) { - x.printStackTrace(); - return; - } - } - } - - private static int parseDigits(Token token) { - return Integer.parseInt(token.image, 10); - } - - private static int getMilitaryZoneOffset(char c) { - if (ignoreMilitaryZoneOffset) - return 0; - - c = Character.toUpperCase(c); - - switch (c) { - case 'A': return 1; - case 'B': return 2; - case 'C': return 3; - case 'D': return 4; - case 'E': return 5; - case 'F': return 6; - case 'G': return 7; - case 'H': return 8; - case 'I': return 9; - case 'K': return 10; - case 'L': return 11; - case 'M': return 12; - - case 'N': return -1; - case 'O': return -2; - case 'P': return -3; - case 'Q': return -4; - case 'R': return -5; - case 'S': return -6; - case 'T': return -7; - case 'U': return -8; - case 'V': return -9; - case 'W': return -10; - case 'X': return -11; - case 'Y': return -12; - - case 'Z': return 0; - default: return 0; - } - } - - private static class Time { - private int hour; - private int minute; - private int second; - private int zone; - - public Time(int hour, int minute, int second, int zone) { - this.hour = hour; - this.minute = minute; - this.second = second; - this.zone = zone; - } - - public int getHour() { return hour; } - public int getMinute() { return minute; } - public int getSecond() { return second; } - public int getZone() { return zone; } - } - - private static class Date { - private String year; - private int month; - private int day; - - public Date(String year, int month, int day) { - this.year = year; - this.month = month; - this.day = day; - } - - public String getYear() { return year; } - public int getMonth() { return month; } - public int getDay() { return day; } - } - - final public DateTime parseLine() throws ParseException { - DateTime dt; - dt = date_time(); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 1: - jj_consume_token(1); - break; - default: - jj_la1[0] = jj_gen; - ; - } - jj_consume_token(2); - {if (true) return dt;} - throw new Error("Missing return statement in function"); - } - - final public DateTime parseAll() throws ParseException { - DateTime dt; - dt = date_time(); - jj_consume_token(0); - {if (true) return dt;} - throw new Error("Missing return statement in function"); - } - - final public DateTime date_time() throws ParseException { - Date d; Time t; - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - day_of_week(); - jj_consume_token(3); - break; - default: - jj_la1[1] = jj_gen; - ; - } - d = date(); - t = time(); - {if (true) return new DateTime( - d.getYear(), - d.getMonth(), - d.getDay(), - t.getHour(), - t.getMinute(), - t.getSecond(), - t.getZone());} // time zone offset - - throw new Error("Missing return statement in function"); - } - - final public String day_of_week() throws ParseException { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 4: - jj_consume_token(4); - break; - case 5: - jj_consume_token(5); - break; - case 6: - jj_consume_token(6); - break; - case 7: - jj_consume_token(7); - break; - case 8: - jj_consume_token(8); - break; - case 9: - jj_consume_token(9); - break; - case 10: - jj_consume_token(10); - break; - default: - jj_la1[2] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - {if (true) return token.image;} - throw new Error("Missing return statement in function"); - } - - final public Date date() throws ParseException { - int d, m; String y; - d = day(); - m = month(); - y = year(); - {if (true) return new Date(y, m, d);} - throw new Error("Missing return statement in function"); - } - - final public int day() throws ParseException { - Token t; - t = jj_consume_token(DIGITS); - {if (true) return parseDigits(t);} - throw new Error("Missing return statement in function"); - } - - final public int month() throws ParseException { - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 11: - jj_consume_token(11); - {if (true) return 1;} - break; - case 12: - jj_consume_token(12); - {if (true) return 2;} - break; - case 13: - jj_consume_token(13); - {if (true) return 3;} - break; - case 14: - jj_consume_token(14); - {if (true) return 4;} - break; - case 15: - jj_consume_token(15); - {if (true) return 5;} - break; - case 16: - jj_consume_token(16); - {if (true) return 6;} - break; - case 17: - jj_consume_token(17); - {if (true) return 7;} - break; - case 18: - jj_consume_token(18); - {if (true) return 8;} - break; - case 19: - jj_consume_token(19); - {if (true) return 9;} - break; - case 20: - jj_consume_token(20); - {if (true) return 10;} - break; - case 21: - jj_consume_token(21); - {if (true) return 11;} - break; - case 22: - jj_consume_token(22); - {if (true) return 12;} - break; - default: - jj_la1[3] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - throw new Error("Missing return statement in function"); - } - - final public String year() throws ParseException { - Token t; - t = jj_consume_token(DIGITS); - {if (true) return t.image;} - throw new Error("Missing return statement in function"); - } - - final public Time time() throws ParseException { - int h, m, s=0, z; - h = hour(); - jj_consume_token(23); - m = minute(); - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 23: - jj_consume_token(23); - s = second(); - break; - default: - jj_la1[4] = jj_gen; - ; - } - z = zone(); - {if (true) return new Time(h, m, s, z);} - throw new Error("Missing return statement in function"); - } - - final public int hour() throws ParseException { - Token t; - t = jj_consume_token(DIGITS); - {if (true) return parseDigits(t);} - throw new Error("Missing return statement in function"); - } - - final public int minute() throws ParseException { - Token t; - t = jj_consume_token(DIGITS); - {if (true) return parseDigits(t);} - throw new Error("Missing return statement in function"); - } - - final public int second() throws ParseException { - Token t; - t = jj_consume_token(DIGITS); - {if (true) return parseDigits(t);} - throw new Error("Missing return statement in function"); - } - - final public int zone() throws ParseException { - Token t, u; int z; - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case OFFSETDIR: - t = jj_consume_token(OFFSETDIR); - u = jj_consume_token(DIGITS); - z=parseDigits(u)*(t.image.equals("-") ? -1 : 1); - break; - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - case 32: - case 33: - case 34: - case MILITARY_ZONE: - z = obs_zone(); - break; - default: - jj_la1[5] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - {if (true) return z;} - throw new Error("Missing return statement in function"); - } - - final public int obs_zone() throws ParseException { - Token t; int z; - switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { - case 25: - jj_consume_token(25); - z=0; - break; - case 26: - jj_consume_token(26); - z=0; - break; - case 27: - jj_consume_token(27); - z=-5; - break; - case 28: - jj_consume_token(28); - z=-4; - break; - case 29: - jj_consume_token(29); - z=-6; - break; - case 30: - jj_consume_token(30); - z=-5; - break; - case 31: - jj_consume_token(31); - z=-7; - break; - case 32: - jj_consume_token(32); - z=-6; - break; - case 33: - jj_consume_token(33); - z=-8; - break; - case 34: - jj_consume_token(34); - z=-7; - break; - case MILITARY_ZONE: - t = jj_consume_token(MILITARY_ZONE); - z=getMilitaryZoneOffset(t.image.charAt(0)); - break; - default: - jj_la1[6] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - {if (true) return z * 100;} - throw new Error("Missing return statement in function"); - } - - public DateTimeParserTokenManager token_source; - SimpleCharStream jj_input_stream; - public Token token, jj_nt; - private int jj_ntk; - private int jj_gen; - final private int[] jj_la1 = new int[7]; - static private int[] jj_la1_0; - static private int[] jj_la1_1; - static { - jj_la1_0(); - jj_la1_1(); - } - private static void jj_la1_0() { - jj_la1_0 = new int[] {0x2,0x7f0,0x7f0,0x7ff800,0x800000,0xff000000,0xfe000000,}; - } - private static void jj_la1_1() { - jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0xf,0xf,}; - } - - public DateTimeParser(java.io.InputStream stream) { - this(stream, null); - } - public DateTimeParser(java.io.InputStream stream, String encoding) { - try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source = new DateTimeParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 7; i++) jj_la1[i] = -1; - } - - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - public void ReInit(java.io.InputStream stream, String encoding) { - try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 7; i++) jj_la1[i] = -1; - } - - public DateTimeParser(java.io.Reader stream) { - jj_input_stream = new SimpleCharStream(stream, 1, 1); - token_source = new DateTimeParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 7; i++) jj_la1[i] = -1; - } - - public void ReInit(java.io.Reader stream) { - jj_input_stream.ReInit(stream, 1, 1); - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 7; i++) jj_la1[i] = -1; - } - - public DateTimeParser(DateTimeParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 7; i++) jj_la1[i] = -1; - } - - public void ReInit(DateTimeParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 7; i++) jj_la1[i] = -1; - } - - final private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - if (token.kind == kind) { - jj_gen++; - return token; - } - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - final public Token getNextToken() { - if (token.next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - jj_gen++; - return token; - } - - final public Token getToken(int index) { - Token t = token; - for (int i = 0; i < index; i++) { - if (t.next != null) t = t.next; - else t = t.next = token_source.getNextToken(); - } - return t; - } - - final private int jj_ntk() { - if ((jj_nt=token.next) == null) - return (jj_ntk = (token.next=token_source.getNextToken()).kind); - else - return (jj_ntk = jj_nt.kind); - } - - private Vector jj_expentries = new Vector(); - private int[] jj_expentry; - private int jj_kind = -1; - - public ParseException generateParseException() { - jj_expentries.removeAllElements(); - boolean[] la1tokens = new boolean[49]; - for (int i = 0; i < 49; i++) { - la1tokens[i] = false; - } - if (jj_kind >= 0) { - la1tokens[jj_kind] = true; - jj_kind = -1; - } - for (int i = 0; i < 7; i++) { - if (jj_la1[i] == jj_gen) { - for (int j = 0; j < 32; j++) { - if ((jj_la1_0[i] & (1<", - "\"\\r\"", - "\"\\n\"", - "\",\"", - "\"Mon\"", - "\"Tue\"", - "\"Wed\"", - "\"Thu\"", - "\"Fri\"", - "\"Sat\"", - "\"Sun\"", - "\"Jan\"", - "\"Feb\"", - "\"Mar\"", - "\"Apr\"", - "\"May\"", - "\"Jun\"", - "\"Jul\"", - "\"Aug\"", - "\"Sep\"", - "\"Oct\"", - "\"Nov\"", - "\"Dec\"", - "\":\"", - "", - "\"UT\"", - "\"GMT\"", - "\"EST\"", - "\"EDT\"", - "\"CST\"", - "\"CDT\"", - "\"MST\"", - "\"MDT\"", - "\"PST\"", - "\"PDT\"", - "", - "", - "\"(\"", - "\")\"", - "", - "\"(\"", - "", - "", - "\"(\"", - "\")\"", - "", - "", - "", - "", - }; - -} diff --git a/apache/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java b/apache/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java deleted file mode 100644 index 4b2d2fd95565bad41ef1105d2f4ea907cd93103c..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/parser/DateTimeParserTokenManager.java +++ /dev/null @@ -1,882 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. DateTimeParserTokenManager.java */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.datetime.parser; -import org.apache.james.mime4j.field.datetime.DateTime; -import java.util.Calendar; - -public class DateTimeParserTokenManager implements DateTimeParserConstants -{ - // Keeps track of how many levels of comment nesting - // we've encountered. This is only used when the 2nd - // level is reached, for example ((this)), not (this). - // This is because the outermost level must be treated - // specially anyway, because the outermost ")" has a - // different token type than inner ")" instances. - static int commentNest; - public java.io.PrintStream debugStream = System.out; - public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } -private final int jjStopStringLiteralDfa_0(int pos, long active0) -{ - switch (pos) - { - case 0: - if ((active0 & 0x7fe7cf7f0L) != 0L) - { - jjmatchedKind = 35; - return -1; - } - return -1; - case 1: - if ((active0 & 0x7fe7cf7f0L) != 0L) - { - if (jjmatchedPos == 0) - { - jjmatchedKind = 35; - jjmatchedPos = 0; - } - return -1; - } - return -1; - default : - return -1; - } -} -private final int jjStartNfa_0(int pos, long active0) -{ - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); -} -private final int jjStopAtPos(int pos, int kind) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; -} -private final int jjStartNfaWithStates_0(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_0(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_0() -{ - switch(curChar) - { - case 10: - return jjStopAtPos(0, 2); - case 13: - return jjStopAtPos(0, 1); - case 40: - return jjStopAtPos(0, 37); - case 44: - return jjStopAtPos(0, 3); - case 58: - return jjStopAtPos(0, 23); - case 65: - return jjMoveStringLiteralDfa1_0(0x44000L); - case 67: - return jjMoveStringLiteralDfa1_0(0x60000000L); - case 68: - return jjMoveStringLiteralDfa1_0(0x400000L); - case 69: - return jjMoveStringLiteralDfa1_0(0x18000000L); - case 70: - return jjMoveStringLiteralDfa1_0(0x1100L); - case 71: - return jjMoveStringLiteralDfa1_0(0x4000000L); - case 74: - return jjMoveStringLiteralDfa1_0(0x30800L); - case 77: - return jjMoveStringLiteralDfa1_0(0x18000a010L); - case 78: - return jjMoveStringLiteralDfa1_0(0x200000L); - case 79: - return jjMoveStringLiteralDfa1_0(0x100000L); - case 80: - return jjMoveStringLiteralDfa1_0(0x600000000L); - case 83: - return jjMoveStringLiteralDfa1_0(0x80600L); - case 84: - return jjMoveStringLiteralDfa1_0(0xa0L); - case 85: - return jjMoveStringLiteralDfa1_0(0x2000000L); - case 87: - return jjMoveStringLiteralDfa1_0(0x40L); - default : - return jjMoveNfa_0(0, 0); - } -} -private final int jjMoveStringLiteralDfa1_0(long active0) -{ - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(0, active0); - return 1; - } - switch(curChar) - { - case 68: - return jjMoveStringLiteralDfa2_0(active0, 0x550000000L); - case 77: - return jjMoveStringLiteralDfa2_0(active0, 0x4000000L); - case 83: - return jjMoveStringLiteralDfa2_0(active0, 0x2a8000000L); - case 84: - if ((active0 & 0x2000000L) != 0L) - return jjStopAtPos(1, 25); - break; - case 97: - return jjMoveStringLiteralDfa2_0(active0, 0xaa00L); - case 99: - return jjMoveStringLiteralDfa2_0(active0, 0x100000L); - case 101: - return jjMoveStringLiteralDfa2_0(active0, 0x481040L); - case 104: - return jjMoveStringLiteralDfa2_0(active0, 0x80L); - case 111: - return jjMoveStringLiteralDfa2_0(active0, 0x200010L); - case 112: - return jjMoveStringLiteralDfa2_0(active0, 0x4000L); - case 114: - return jjMoveStringLiteralDfa2_0(active0, 0x100L); - case 117: - return jjMoveStringLiteralDfa2_0(active0, 0x70420L); - default : - break; - } - return jjStartNfa_0(0, active0); -} -private final int jjMoveStringLiteralDfa2_0(long old0, long active0) -{ - if (((active0 &= old0)) == 0L) - return jjStartNfa_0(0, old0); - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(1, active0); - return 2; - } - switch(curChar) - { - case 84: - if ((active0 & 0x4000000L) != 0L) - return jjStopAtPos(2, 26); - else if ((active0 & 0x8000000L) != 0L) - return jjStopAtPos(2, 27); - else if ((active0 & 0x10000000L) != 0L) - return jjStopAtPos(2, 28); - else if ((active0 & 0x20000000L) != 0L) - return jjStopAtPos(2, 29); - else if ((active0 & 0x40000000L) != 0L) - return jjStopAtPos(2, 30); - else if ((active0 & 0x80000000L) != 0L) - return jjStopAtPos(2, 31); - else if ((active0 & 0x100000000L) != 0L) - return jjStopAtPos(2, 32); - else if ((active0 & 0x200000000L) != 0L) - return jjStopAtPos(2, 33); - else if ((active0 & 0x400000000L) != 0L) - return jjStopAtPos(2, 34); - break; - case 98: - if ((active0 & 0x1000L) != 0L) - return jjStopAtPos(2, 12); - break; - case 99: - if ((active0 & 0x400000L) != 0L) - return jjStopAtPos(2, 22); - break; - case 100: - if ((active0 & 0x40L) != 0L) - return jjStopAtPos(2, 6); - break; - case 101: - if ((active0 & 0x20L) != 0L) - return jjStopAtPos(2, 5); - break; - case 103: - if ((active0 & 0x40000L) != 0L) - return jjStopAtPos(2, 18); - break; - case 105: - if ((active0 & 0x100L) != 0L) - return jjStopAtPos(2, 8); - break; - case 108: - if ((active0 & 0x20000L) != 0L) - return jjStopAtPos(2, 17); - break; - case 110: - if ((active0 & 0x10L) != 0L) - return jjStopAtPos(2, 4); - else if ((active0 & 0x400L) != 0L) - return jjStopAtPos(2, 10); - else if ((active0 & 0x800L) != 0L) - return jjStopAtPos(2, 11); - else if ((active0 & 0x10000L) != 0L) - return jjStopAtPos(2, 16); - break; - case 112: - if ((active0 & 0x80000L) != 0L) - return jjStopAtPos(2, 19); - break; - case 114: - if ((active0 & 0x2000L) != 0L) - return jjStopAtPos(2, 13); - else if ((active0 & 0x4000L) != 0L) - return jjStopAtPos(2, 14); - break; - case 116: - if ((active0 & 0x200L) != 0L) - return jjStopAtPos(2, 9); - else if ((active0 & 0x100000L) != 0L) - return jjStopAtPos(2, 20); - break; - case 117: - if ((active0 & 0x80L) != 0L) - return jjStopAtPos(2, 7); - break; - case 118: - if ((active0 & 0x200000L) != 0L) - return jjStopAtPos(2, 21); - break; - case 121: - if ((active0 & 0x8000L) != 0L) - return jjStopAtPos(2, 15); - break; - default : - break; - } - return jjStartNfa_0(1, active0); -} -private final void jjCheckNAdd(int state) -{ - if (jjrounds[state] != jjround) - { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } -} -private final void jjAddStates(int start, int end) -{ - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); -} -private final void jjCheckNAddTwoStates(int state1, int state2) -{ - jjCheckNAdd(state1); - jjCheckNAdd(state2); -} -private final void jjCheckNAddStates(int start, int end) -{ - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); -} -private final void jjCheckNAddStates(int start) -{ - jjCheckNAdd(jjnextStates[start]); - jjCheckNAdd(jjnextStates[start + 1]); -} -private final int jjMoveNfa_0(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 4; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0x3ff000000000000L & l) != 0L) - { - if (kind > 46) - kind = 46; - jjCheckNAdd(3); - } - else if ((0x100000200L & l) != 0L) - { - if (kind > 36) - kind = 36; - jjCheckNAdd(2); - } - else if ((0x280000000000L & l) != 0L) - { - if (kind > 24) - kind = 24; - } - break; - case 2: - if ((0x100000200L & l) == 0L) - break; - kind = 36; - jjCheckNAdd(2); - break; - case 3: - if ((0x3ff000000000000L & l) == 0L) - break; - kind = 46; - jjCheckNAdd(3); - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0x7fffbfe07fffbfeL & l) != 0L) - kind = 35; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 4 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_1(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_1(int pos, long active0) -{ - return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_1(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_1(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_1() -{ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 40); - case 41: - return jjStopAtPos(0, 38); - default : - return jjMoveNfa_1(0, 0); - } -} -static final long[] jjbitVec0 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -private final int jjMoveNfa_1(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 41) - kind = 41; - break; - case 1: - if (kind > 39) - kind = 39; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 41) - kind = 41; - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 39) - kind = 39; - break; - case 2: - if (kind > 41) - kind = 41; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 41) - kind = 41; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 39) - kind = 39; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_2(int pos, long active0) -{ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_2(int pos, long active0) -{ - return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); -} -private final int jjStartNfaWithStates_2(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_2(state, pos + 1); -} -private final int jjMoveStringLiteralDfa0_2() -{ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 43); - case 41: - return jjStopAtPos(0, 44); - default : - return jjMoveNfa_2(0, 0); - } -} -private final int jjMoveNfa_2(int startState, int curPos) -{ - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 45) - kind = 45; - break; - case 1: - if (kind > 42) - kind = 42; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if (kind > 45) - kind = 45; - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (kind > 42) - kind = 42; - break; - case 2: - if (kind > 45) - kind = 45; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: do - { - switch(jjstateSet[--i]) - { - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 45) - kind = 45; - break; - case 1: - if ((jjbitVec0[i2] & l2) != 0L && kind > 42) - kind = 42; - break; - default : break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -static final int[] jjnextStates = { -}; -public static final String[] jjstrLiteralImages = { -"", "\15", "\12", "\54", "\115\157\156", "\124\165\145", "\127\145\144", -"\124\150\165", "\106\162\151", "\123\141\164", "\123\165\156", "\112\141\156", -"\106\145\142", "\115\141\162", "\101\160\162", "\115\141\171", "\112\165\156", -"\112\165\154", "\101\165\147", "\123\145\160", "\117\143\164", "\116\157\166", -"\104\145\143", "\72", null, "\125\124", "\107\115\124", "\105\123\124", "\105\104\124", -"\103\123\124", "\103\104\124", "\115\123\124", "\115\104\124", "\120\123\124", -"\120\104\124", null, null, null, null, null, null, null, null, null, null, null, null, null, -null, }; -public static final String[] lexStateNames = { - "DEFAULT", - "INCOMMENT", - "NESTED_COMMENT", -}; -public static final int[] jjnewLexState = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -}; -static final long[] jjtoToken = { - 0x400fffffffffL, -}; -static final long[] jjtoSkip = { - 0x5000000000L, -}; -static final long[] jjtoSpecial = { - 0x1000000000L, -}; -static final long[] jjtoMore = { - 0x3fa000000000L, -}; -protected SimpleCharStream input_stream; -private final int[] jjrounds = new int[4]; -private final int[] jjstateSet = new int[8]; -StringBuffer image; -int jjimageLen; -int lengthOfMatch; -protected char curChar; -public DateTimeParserTokenManager(SimpleCharStream stream){ - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - input_stream = stream; -} -public DateTimeParserTokenManager(SimpleCharStream stream, int lexState){ - this(stream); - SwitchTo(lexState); -} -public void ReInit(SimpleCharStream stream) -{ - jjmatchedPos = jjnewStateCnt = 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); -} -private final void ReInitRounds() -{ - int i; - jjround = 0x80000001; - for (i = 4; i-- > 0;) - jjrounds[i] = 0x80000000; -} -public void ReInit(SimpleCharStream stream, int lexState) -{ - ReInit(stream); - SwitchTo(lexState); -} -public void SwitchTo(int lexState) -{ - if (lexState >= 3 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; -} - -protected Token jjFillToken() -{ - Token t = Token.newToken(jjmatchedKind); - t.kind = jjmatchedKind; - String im = jjstrLiteralImages[jjmatchedKind]; - t.image = (im == null) ? input_stream.GetImage() : im; - t.beginLine = input_stream.getBeginLine(); - t.beginColumn = input_stream.getBeginColumn(); - t.endLine = input_stream.getEndLine(); - t.endColumn = input_stream.getEndColumn(); - return t; -} - -int curLexState = 0; -int defaultLexState = 0; -int jjnewStateCnt; -int jjround; -int jjmatchedPos; -int jjmatchedKind; - -public Token getNextToken() -{ - int kind; - Token specialToken = null; - Token matchedToken; - int curPos = 0; - - EOFLoop : - for (;;) - { - try - { - curChar = input_stream.BeginToken(); - } - catch(java.io.IOException e) - { - jjmatchedKind = 0; - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - return matchedToken; - } - image = null; - jjimageLen = 0; - - for (;;) - { - switch(curLexState) - { - case 0: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - break; - case 1: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - break; - case 2: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - break; - } - if (jjmatchedKind != 0x7fffffff) - { - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - } - else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - if (specialToken == null) - specialToken = matchedToken; - else - { - matchedToken.specialToken = specialToken; - specialToken = (specialToken.next = matchedToken); - } - } - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - MoreLexicalActions(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - curPos = 0; - jjmatchedKind = 0x7fffffff; - try { - curChar = input_stream.readChar(); - continue; - } - catch (java.io.IOException e1) { } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { input_stream.readChar(); input_stream.backup(1); } - catch (java.io.IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } - else - error_column++; - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } - } -} - -void MoreLexicalActions() -{ - jjimageLen += (lengthOfMatch = jjmatchedPos + 1); - switch(jjmatchedKind) - { - case 39 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 40 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - commentNest = 1; - break; - case 42 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - image.deleteCharAt(image.length() - 2); - break; - case 43 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - ++commentNest; - break; - case 44 : - if (image == null) - image = new StringBuffer(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); - break; - default : - break; - } -} -} diff --git a/apache/org/apache/james/mime4j/field/datetime/parser/ParseException.java b/apache/org/apache/james/mime4j/field/datetime/parser/ParseException.java deleted file mode 100644 index 13b3ff097a0f88a0dd8d6797d9d45b588a8e218a..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/parser/ParseException.java +++ /dev/null @@ -1,207 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.datetime.parser; - -/** - * This exception is thrown when parse errors are encountered. - * You can explicitly create objects of this exception type by - * calling the method generateParseException in the generated - * parser. - * - * You can modify this class to customize your error reporting - * mechanisms so long as you retain the public fields. - */ -public class ParseException extends Exception { - - /** - * This constructor is used by the method "generateParseException" - * in the generated parser. Calling this constructor generates - * a new object of this type with the fields "currentToken", - * "expectedTokenSequences", and "tokenImage" set. The boolean - * flag "specialConstructor" is also set to true to indicate that - * this constructor was used to create this object. - * This constructor calls its super class with the empty string - * to force the "toString" method of parent class "Throwable" to - * print the error message in the form: - * ParseException: - */ - public ParseException(Token currentTokenVal, - int[][] expectedTokenSequencesVal, - String[] tokenImageVal - ) - { - super(""); - specialConstructor = true; - currentToken = currentTokenVal; - expectedTokenSequences = expectedTokenSequencesVal; - tokenImage = tokenImageVal; - } - - /** - * The following constructors are for use by you for whatever - * purpose you can think of. Constructing the exception in this - * manner makes the exception behave in the normal way - i.e., as - * documented in the class "Throwable". The fields "errorToken", - * "expectedTokenSequences", and "tokenImage" do not contain - * relevant information. The JavaCC generated code does not use - * these constructors. - */ - - public ParseException() { - super(); - specialConstructor = false; - } - - public ParseException(String message) { - super(message); - specialConstructor = false; - } - - /** - * This variable determines which constructor was used to create - * this object and thereby affects the semantics of the - * "getMessage" method (see below). - */ - protected boolean specialConstructor; - - /** - * This is the last token that has been consumed successfully. If - * this object has been created due to a parse error, the token - * followng this token will (therefore) be the first error token. - */ - public Token currentToken; - - /** - * Each entry in this array is an array of integers. Each array - * of integers represents a sequence of tokens (by their ordinal - * values) that is expected at this point of the parse. - */ - public int[][] expectedTokenSequences; - - /** - * This is a reference to the "tokenImage" array of the generated - * parser within which the parse error occurred. This array is - * defined in the generated ...Constants interface. - */ - public String[] tokenImage; - - /** - * This method has the standard behavior when this object has been - * created using the standard constructors. Otherwise, it uses - * "currentToken" and "expectedTokenSequences" to generate a parse - * error message and returns it. If this object has been created - * due to a parse error, and you do not catch it (it gets thrown - * from the parser), then this method is called during the printing - * of the final stack trace, and hence the correct error message - * gets displayed. - */ - public String getMessage() { - if (!specialConstructor) { - return super.getMessage(); - } - StringBuffer expected = new StringBuffer(); - int maxSize = 0; - for (int i = 0; i < expectedTokenSequences.length; i++) { - if (maxSize < expectedTokenSequences[i].length) { - maxSize = expectedTokenSequences[i].length; - } - for (int j = 0; j < expectedTokenSequences[i].length; j++) { - expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" "); - } - if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { - expected.append("..."); - } - expected.append(eol).append(" "); - } - String retval = "Encountered \""; - Token tok = currentToken.next; - for (int i = 0; i < maxSize; i++) { - if (i != 0) retval += " "; - if (tok.kind == 0) { - retval += tokenImage[0]; - break; - } - retval += add_escapes(tok.image); - tok = tok.next; - } - retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; - retval += "." + eol; - if (expectedTokenSequences.length == 1) { - retval += "Was expecting:" + eol + " "; - } else { - retval += "Was expecting one of:" + eol + " "; - } - retval += expected.toString(); - return retval; - } - - /** - * The end of line string for this machine. - */ - protected String eol = System.getProperty("line.separator", "\n"); - - /** - * Used to convert raw characters to their escaped version - * when these raw version cannot be used as part of an ASCII - * string literal. - */ - protected String add_escapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case 0 : - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - -} diff --git a/apache/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java b/apache/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java deleted file mode 100644 index 2724529f7c57fe31eead92c84908616cd4583fb1..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/parser/SimpleCharStream.java +++ /dev/null @@ -1,454 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.datetime.parser; - -/** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (without unicode processing). - */ - -public class SimpleCharStream -{ - public static final boolean staticFlag = false; - int bufsize; - int available; - int tokenBegin; - public int bufpos = -1; - protected int bufline[]; - protected int bufcolumn[]; - - protected int column = 0; - protected int line = 1; - - protected boolean prevCharIsCR = false; - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] buffer; - protected int maxNextCharInd = 0; - protected int inBuf = 0; - protected int tabSize = 8; - - protected void setTabSize(int i) { tabSize = i; } - protected int getTabSize(int i) { return tabSize; } - - - protected void ExpandBuff(boolean wrapAround) - { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try - { - if (wrapAround) - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, - bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos += (bufsize - tokenBegin)); - } - else - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos -= tokenBegin); - } - } - catch (Throwable t) - { - throw new Error(t.getMessage()); - } - - - bufsize += 2048; - available = bufsize; - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException - { - if (maxNextCharInd == available) - { - if (available == bufsize) - { - if (tokenBegin > 2048) - { - bufpos = maxNextCharInd = 0; - available = tokenBegin; - } - else if (tokenBegin < 0) - bufpos = maxNextCharInd = 0; - else - ExpandBuff(false); - } - else if (available > tokenBegin) - available = bufsize; - else if ((tokenBegin - available) < 2048) - ExpandBuff(true); - else - available = tokenBegin; - } - - int i; - try { - if ((i = inputStream.read(buffer, maxNextCharInd, - available - maxNextCharInd)) == -1) - { - inputStream.close(); - throw new java.io.IOException(); - } - else - maxNextCharInd += i; - return; - } - catch(java.io.IOException e) { - --bufpos; - backup(0); - if (tokenBegin == -1) - tokenBegin = bufpos; - throw e; - } - } - - public char BeginToken() throws java.io.IOException - { - tokenBegin = -1; - char c = readChar(); - tokenBegin = bufpos; - - return c; - } - - protected void UpdateLineColumn(char c) - { - column++; - - if (prevCharIsLF) - { - prevCharIsLF = false; - line += (column = 1); - } - else if (prevCharIsCR) - { - prevCharIsCR = false; - if (c == '\n') - { - prevCharIsLF = true; - } - else - line += (column = 1); - } - - switch (c) - { - case '\r' : - prevCharIsCR = true; - break; - case '\n' : - prevCharIsLF = true; - break; - case '\t' : - column--; - column += (tabSize - (column % tabSize)); - break; - default : - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - - public char readChar() throws java.io.IOException - { - if (inBuf > 0) - { - --inBuf; - - if (++bufpos == bufsize) - bufpos = 0; - - return buffer[bufpos]; - } - - if (++bufpos >= maxNextCharInd) - FillBuff(); - - char c = buffer[bufpos]; - - UpdateLineColumn(c); - return (c); - } - - /** - * @deprecated - * @see #getEndColumn - */ - @Deprecated - public int getColumn() { - return bufcolumn[bufpos]; - } - - /** - * @deprecated - * @see #getEndLine - */ - @Deprecated - public int getLine() { - return bufline[bufpos]; - } - - public int getEndColumn() { - return bufcolumn[bufpos]; - } - - public int getEndLine() { - return bufline[bufpos]; - } - - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - - public int getBeginLine() { - return bufline[tokenBegin]; - } - - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) - bufpos += bufsize; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.Reader dstream) - { - this(dstream, 1, 1, 4096); - } - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) - { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - bufpos = -1; - } - - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - - public void ReInit(java.io.Reader dstream) - { - ReInit(dstream, 1, 1, 4096); - } - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, 1, 1, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream) - { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream) - { - ReInit(dstream, 1, 1, 4096); - } - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - public String GetImage() - { - if (bufpos >= tokenBegin) - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - else - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - - public char[] GetSuffix(int len) - { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - else - { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - public void Done() - { - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - */ - public void adjustBeginLineColumn(int newLine, int newCol) - { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) - { - len = bufpos - tokenBegin + inBuf + 1; - } - else - { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k = 0; - int nextColDiff = 0, columnDiff = 0; - - while (i < len && - bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) - { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) - { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) - { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) - bufline[j] = newLine++; - else - bufline[j] = newLine; - } - } - - line = bufline[j]; - column = bufcolumn[j]; - } - -} diff --git a/apache/org/apache/james/mime4j/field/datetime/parser/Token.java b/apache/org/apache/james/mime4j/field/datetime/parser/Token.java deleted file mode 100644 index 0927a09212d788d846ab83f6aeccd355d14a05c6..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/parser/Token.java +++ /dev/null @@ -1,96 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.datetime.parser; - -/** - * Describes the input token stream. - */ - -public class Token { - - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** - * beginLine and beginColumn describe the position of the first character - * of this token; endLine and endColumn describe the position of the - * last character of this token. - */ - public int beginLine, beginColumn, endLine, endColumn; - - /** - * The string image of the token. - */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** - * Returns the image. - */ - public String toString() - { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simlpy add something like : - * - * case MyParserConstants.ID : return new IDToken(); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use it in your lexical actions. - */ - public static final Token newToken(int ofKind) - { - switch(ofKind) - { - default : return new Token(); - } - } - -} diff --git a/apache/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java b/apache/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java deleted file mode 100644 index e7043c1b756d8033a1a9f64902f94b81b3fdedb9..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/field/datetime/parser/TokenMgrError.java +++ /dev/null @@ -1,148 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ -/* - * Copyright 2004 the mime4j 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 org.apache.james.mime4j.field.datetime.parser; - -public class TokenMgrError extends Error -{ - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** - * Lexical error occured. - */ - static final int LEXICAL_ERROR = 0; - - /** - * An attempt wass made to create a second instance of a static token manager. - */ - static final int STATIC_LEXER_ERROR = 1; - - /** - * Tried to change to an invalid lexical state. - */ - static final int INVALID_LEXICAL_STATE = 2; - - /** - * Detected (and bailed out of) an infinite loop in the token manager. - */ - static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - /** - * Replaces unprintable characters by their espaced (or unicode escaped) - * equivalents in the given string - */ - protected static final String addEscapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case 0 : - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - - /** - * Returns a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - * Parameters : - * EOFSeen : indicates if EOF caused the lexicl error - * curLexState : lexical state in which this error occured - * errorLine : line number when the error occured - * errorColumn : column number when the error occured - * errorAfter : prefix that was seen before this error occured - * curchar : the offending character - * Note: You can customize the lexical error message by modifying this method. - */ - protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { - return("Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""); - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - public TokenMgrError() { - } - - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { - this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } -} diff --git a/apache/org/apache/james/mime4j/util/CharsetUtil.java b/apache/org/apache/james/mime4j/util/CharsetUtil.java deleted file mode 100644 index 4e712fcdd0351020e86e562f60495fc4e2099363..0000000000000000000000000000000000000000 --- a/apache/org/apache/james/mime4j/util/CharsetUtil.java +++ /dev/null @@ -1,1249 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you 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 org.apache.james.mime4j.util; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; -import java.util.HashMap; -import java.util.Locale; -import java.util.TreeSet; - -//BEGIN android-changed: Stubbing out logging -import org.apache.james.mime4j.Log; -import org.apache.james.mime4j.LogFactory; -//END android-changed - -/** - * Utility class for working with character sets. It is somewhat similar to - * the Java 1.4 java.nio.charset.Charset class but knows many - * more aliases and is compatible with Java 1.3. It will use a simple detection - * mechanism to detect what character sets the current VM supports. This will - * be a sub-set of the character sets listed in the - * - * Java 1.5 (J2SE5.0) Supported Encodings document. - *

- * The - * IANA Character Sets document has been used to determine the preferred - * MIME character set names and to get a list of known aliases. - *

- * This is a complete list of the character sets known to this class: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Canonical (Java) nameMIME preferredAliases
ASCIIUS-ASCIIANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ISO646-US us IBM367 cp367 csASCII ascii7 646 iso_646.irv:1983
Big5Big5csBig5 CN-Big5 BIG-FIVE BIGFIVE
Big5_HKSCSBig5-HKSCSbig5hkscs
Big5_Solaris?
Cp037IBM037ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl csIBM037
Cp1006?
Cp1025?
Cp1026IBM1026csIBM1026
Cp1046?
Cp1047IBM1047IBM-1047
Cp1097?
Cp1098?
Cp1112?
Cp1122?
Cp1123?
Cp1124?
Cp1140IBM01140CCSID01140 CP01140 ebcdic-us-37+euro
Cp1141IBM01141CCSID01141 CP01141 ebcdic-de-273+euro
Cp1142IBM01142CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro
Cp1143IBM01143CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro
Cp1144IBM01144CCSID01144 CP01144 ebcdic-it-280+euro
Cp1145IBM01145CCSID01145 CP01145 ebcdic-es-284+euro
Cp1146IBM01146CCSID01146 CP01146 ebcdic-gb-285+euro
Cp1147IBM01147CCSID01147 CP01147 ebcdic-fr-297+euro
Cp1148IBM01148CCSID01148 CP01148 ebcdic-international-500+euro
Cp1149IBM01149CCSID01149 CP01149 ebcdic-is-871+euro
Cp1250windows-1250
Cp1251windows-1251
Cp1252windows-1252
Cp1253windows-1253
Cp1254windows-1254
Cp1255windows-1255
Cp1256windows-1256
Cp1257windows-1257
Cp1258windows-1258
Cp1381?
Cp1383?
Cp273IBM273csIBM273
Cp277IBM277EBCDIC-CP-DK EBCDIC-CP-NO csIBM277
Cp278IBM278CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278
Cp280IBM280ebcdic-cp-it csIBM280
Cp284IBM284ebcdic-cp-es csIBM284
Cp285IBM285ebcdic-cp-gb csIBM285
Cp297IBM297ebcdic-cp-fr csIBM297
Cp33722?
Cp420IBM420ebcdic-cp-ar1 csIBM420
Cp424IBM424ebcdic-cp-he csIBM424
Cp437IBM437437 csPC8CodePage437
Cp500IBM500ebcdic-cp-be ebcdic-cp-ch csIBM500
Cp737?
Cp775IBM775csPC775Baltic
Cp838IBM-Thai
Cp850IBM850850 csPC850Multilingual
Cp852IBM852852 csPCp852
Cp855IBM855855 csIBM855
Cp856?
Cp857IBM857857 csIBM857
Cp858IBM00858CCSID00858 CP00858 PC-Multilingual-850+euro
Cp860IBM860860 csIBM860
Cp861IBM861861 cp-is csIBM861
Cp862IBM862862 csPC862LatinHebrew
Cp863IBM863863 csIBM863
Cp864IBM864cp864 csIBM864
Cp865IBM865865 csIBM865
Cp866IBM866866 csIBM866
Cp868IBM868cp-ar csIBM868
Cp869IBM869cp-gr csIBM869
Cp870IBM870ebcdic-cp-roece ebcdic-cp-yu csIBM870
Cp871IBM871ebcdic-cp-is csIBM871
Cp875?
Cp918IBM918ebcdic-cp-ar2 csIBM918
Cp921?
Cp922?
Cp930?
Cp933?
Cp935?
Cp937?
Cp939?
Cp942?
Cp942C?
Cp943?
Cp943C?
Cp948?
Cp949?
Cp949C?
Cp950?
Cp964?
Cp970?
EUC_CNGB2312x-EUC-CN csGB2312 euccn euc-cn gb2312-80 gb2312-1980 CN-GB CN-GB-ISOIR165
EUC_JPEUC-JPcsEUCPkdFmtJapanese Extended_UNIX_Code_Packed_Format_for_Japanese eucjis x-eucjp eucjp x-euc-jp
EUC_JP_LINUX?
EUC_JP_Solaris?
EUC_KREUC-KRcsEUCKR ksc5601 5601 ksc5601_1987 ksc_5601 ksc5601-1987 ks_c_5601-1987 euckr
EUC_TWEUC-TWx-EUC-TW cns11643 euctw
GB18030GB18030gb18030-2000
GBKwindows-936CP936 MS936 ms_936 x-mswin-936
ISCII91?x-ISCII91 iscii
ISO2022CNISO-2022-CN
ISO2022JPISO-2022-JPcsISO2022JP JIS jis_encoding csjisencoding
ISO2022KRISO-2022-KRcsISO2022KR
ISO2022_CN_CNS?
ISO2022_CN_GB?
ISO8859_1ISO-8859-1ISO_8859-1:1987 iso-ir-100 ISO_8859-1 latin1 l1 IBM819 CP819 csISOLatin1 8859_1 819 IBM-819 ISO8859-1 ISO_8859_1
ISO8859_13ISO-8859-13
ISO8859_15ISO-8859-15ISO_8859-15 Latin-9 8859_15 csISOlatin9 IBM923 cp923 923 L9 IBM-923 ISO8859-15 LATIN9 LATIN0 csISOlatin0 ISO8859_15_FDIS
ISO8859_2ISO-8859-2ISO_8859-2:1987 iso-ir-101 ISO_8859-2 latin2 l2 csISOLatin2 8859_2 iso8859_2
ISO8859_3ISO-8859-3ISO_8859-3:1988 iso-ir-109 ISO_8859-3 latin3 l3 csISOLatin3 8859_3
ISO8859_4ISO-8859-4ISO_8859-4:1988 iso-ir-110 ISO_8859-4 latin4 l4 csISOLatin4 8859_4
ISO8859_5ISO-8859-5ISO_8859-5:1988 iso-ir-144 ISO_8859-5 cyrillic csISOLatinCyrillic 8859_5
ISO8859_6ISO-8859-6ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ECMA-114 ASMO-708 arabic csISOLatinArabic 8859_6
ISO8859_7ISO-8859-7ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ELOT_928 ECMA-118 greek greek8 csISOLatinGreek 8859_7 sun_eu_greek
ISO8859_8ISO-8859-8ISO_8859-8:1988 iso-ir-138 ISO_8859-8 hebrew csISOLatinHebrew 8859_8
ISO8859_9ISO-8859-9ISO_8859-9:1989 iso-ir-148 ISO_8859-9 latin5 l5 csISOLatin5 8859_9
JISAutoDetect?
JIS_C6626-1983JIS_C6626-1983x-JIS0208 JIS0208 csISO87JISX0208 x0208 JIS_X0208-1983 iso-ir-87
JIS_X0201JIS_X0201X0201 JIS0201 csHalfWidthKatakana
JIS_X0212-1990JIS_X0212-1990iso-ir-159 x0212 JIS0212 csISO159JISX02121990
KOI8_RKOI8-RcsKOI8R koi8
MS874windows-874cp874
MS932Windows-31Jwindows-932 csWindows31J x-ms-cp932
MS949windows-949windows949 ms_949 x-windows-949
MS950windows-950x-windows-950
MS950_HKSCS
MacArabic?
MacCentralEurope?
MacCroatian?
MacCyrillic?
MacDingbat?
MacGreekMacGreek
MacHebrew?
MacIceland?
MacRomanMacRomanMacintosh MAC csMacintosh
MacRomania?
MacSymbol?
MacThai?
MacTurkish?
MacUkraine?
SJISShift_JISMS_Kanji csShiftJIS shift-jis x-sjis pck
TIS620TIS-620
UTF-16UTF-16UTF_16
UTF8UTF-8
UnicodeBig?
UnicodeBigUnmarkedUTF-16BEX-UTF-16BE UTF_16BE ISO-10646-UCS-2
UnicodeLittle?
UnicodeLittleUnmarkedUTF-16LEUTF_16LE X-UTF-16LE
x-Johabjohabjohab cp1361 ms1361 ksc5601-1992 ksc5601_1992
x-iso-8859-11?
- * - * - * @version $Id: CharsetUtil.java,v 1.1 2004/10/25 07:26:46 ntherning Exp $ - */ -public class CharsetUtil { - private static Log log = LogFactory.getLog(CharsetUtil.class); - - private static class Charset implements Comparable { - private String canonical = null; - private String mime = null; - private String[] aliases = null; - - private Charset(String canonical, String mime, String[] aliases) { - this.canonical = canonical; - this.mime = mime; - this.aliases = aliases; - } - - public int compareTo(Charset c) { - return this.canonical.compareTo(c.canonical); - } - } - - private static Charset[] JAVA_CHARSETS = { - new Charset("ISO8859_1", "ISO-8859-1", - new String[] {"ISO_8859-1:1987", "iso-ir-100", "ISO_8859-1", - "latin1", "l1", "IBM819", "CP819", - "csISOLatin1", "8859_1", "819", "IBM-819", - "ISO8859-1", "ISO_8859_1"}), - new Charset("ISO8859_2", "ISO-8859-2", - new String[] {"ISO_8859-2:1987", "iso-ir-101", "ISO_8859-2", - "latin2", "l2", "csISOLatin2", "8859_2", - "iso8859_2"}), - new Charset("ISO8859_3", "ISO-8859-3", new String[] {"ISO_8859-3:1988", "iso-ir-109", "ISO_8859-3", "latin3", "l3", "csISOLatin3", "8859_3"}), - new Charset("ISO8859_4", "ISO-8859-4", - new String[] {"ISO_8859-4:1988", "iso-ir-110", "ISO_8859-4", - "latin4", "l4", "csISOLatin4", "8859_4"}), - new Charset("ISO8859_5", "ISO-8859-5", - new String[] {"ISO_8859-5:1988", "iso-ir-144", "ISO_8859-5", - "cyrillic", "csISOLatinCyrillic", "8859_5"}), - new Charset("ISO8859_6", "ISO-8859-6", new String[] {"ISO_8859-6:1987", "iso-ir-127", "ISO_8859-6", "ECMA-114", "ASMO-708", "arabic", "csISOLatinArabic", "8859_6"}), - new Charset("ISO8859_7", "ISO-8859-7", - new String[] {"ISO_8859-7:1987", "iso-ir-126", "ISO_8859-7", - "ELOT_928", "ECMA-118", "greek", "greek8", - "csISOLatinGreek", "8859_7", "sun_eu_greek"}), - new Charset("ISO8859_8", "ISO-8859-8", new String[] {"ISO_8859-8:1988", "iso-ir-138", "ISO_8859-8", "hebrew", "csISOLatinHebrew", "8859_8"}), - new Charset("ISO8859_9", "ISO-8859-9", - new String[] {"ISO_8859-9:1989", "iso-ir-148", "ISO_8859-9", - "latin5", "l5", "csISOLatin5", "8859_9"}), - - new Charset("ISO8859_13", "ISO-8859-13", new String[] {}), - new Charset("ISO8859_15", "ISO-8859-15", - new String[] {"ISO_8859-15", "Latin-9", "8859_15", - "csISOlatin9", "IBM923", "cp923", "923", "L9", - "IBM-923", "ISO8859-15", "LATIN9", "LATIN0", - "csISOlatin0", "ISO8859_15_FDIS"}), - new Charset("KOI8_R", "KOI8-R", new String[] {"csKOI8R", "koi8"}), - new Charset("ASCII", "US-ASCII", - new String[] {"ANSI_X3.4-1968", "iso-ir-6", - "ANSI_X3.4-1986", "ISO_646.irv:1991", - "ISO646-US", "us", "IBM367", "cp367", - "csASCII", "ascii7", "646", "iso_646.irv:1983"}), - new Charset("UTF8", "UTF-8", new String[] {}), - new Charset("UTF-16", "UTF-16", new String[] {"UTF_16"}), - new Charset("UnicodeBigUnmarked", "UTF-16BE", new String[] {"X-UTF-16BE", "UTF_16BE", "ISO-10646-UCS-2"}), - new Charset("UnicodeLittleUnmarked", "UTF-16LE", new String[] {"UTF_16LE", "X-UTF-16LE"}), - new Charset("Big5", "Big5", new String[] {"csBig5", "CN-Big5", "BIG-FIVE", "BIGFIVE"}), - new Charset("Big5_HKSCS", "Big5-HKSCS", new String[] {"big5hkscs"}), - new Charset("EUC_JP", "EUC-JP", - new String[] {"csEUCPkdFmtJapanese", - "Extended_UNIX_Code_Packed_Format_for_Japanese", - "eucjis", "x-eucjp", "eucjp", "x-euc-jp"}), - new Charset("EUC_KR", "EUC-KR", - new String[] {"csEUCKR", "ksc5601", "5601", "ksc5601_1987", - "ksc_5601", "ksc5601-1987", "ks_c_5601-1987", - "euckr"}), - new Charset("GB18030", "GB18030", new String[] {"gb18030-2000"}), - new Charset("EUC_CN", "GB2312", new String[] {"x-EUC-CN", "csGB2312", "euccn", "euc-cn", "gb2312-80", "gb2312-1980", "CN-GB", "CN-GB-ISOIR165"}), - new Charset("GBK", "windows-936", new String[] {"CP936", "MS936", "ms_936", "x-mswin-936"}), - - new Charset("Cp037", "IBM037", new String[] {"ebcdic-cp-us", "ebcdic-cp-ca", "ebcdic-cp-wt", "ebcdic-cp-nl", "csIBM037"}), - new Charset("Cp273", "IBM273", new String[] {"csIBM273"}), - new Charset("Cp277", "IBM277", new String[] {"EBCDIC-CP-DK", "EBCDIC-CP-NO", "csIBM277"}), - new Charset("Cp278", "IBM278", new String[] {"CP278", "ebcdic-cp-fi", "ebcdic-cp-se", "csIBM278"}), - new Charset("Cp280", "IBM280", new String[] {"ebcdic-cp-it", "csIBM280"}), - new Charset("Cp284", "IBM284", new String[] {"ebcdic-cp-es", "csIBM284"}), - new Charset("Cp285", "IBM285", new String[] {"ebcdic-cp-gb", "csIBM285"}), - new Charset("Cp297", "IBM297", new String[] {"ebcdic-cp-fr", "csIBM297"}), - new Charset("Cp420", "IBM420", new String[] {"ebcdic-cp-ar1", "csIBM420"}), - new Charset("Cp424", "IBM424", new String[] {"ebcdic-cp-he", "csIBM424"}), - new Charset("Cp437", "IBM437", new String[] {"437", "csPC8CodePage437"}), - new Charset("Cp500", "IBM500", new String[] {"ebcdic-cp-be", "ebcdic-cp-ch", "csIBM500"}), - new Charset("Cp775", "IBM775", new String[] {"csPC775Baltic"}), - new Charset("Cp838", "IBM-Thai", new String[] {}), - new Charset("Cp850", "IBM850", new String[] {"850", "csPC850Multilingual"}), - new Charset("Cp852", "IBM852", new String[] {"852", "csPCp852"}), - new Charset("Cp855", "IBM855", new String[] {"855", "csIBM855"}), - new Charset("Cp857", "IBM857", new String[] {"857", "csIBM857"}), - new Charset("Cp858", "IBM00858", - new String[] {"CCSID00858", "CP00858", - "PC-Multilingual-850+euro"}), - new Charset("Cp860", "IBM860", new String[] {"860", "csIBM860"}), - new Charset("Cp861", "IBM861", new String[] {"861", "cp-is", "csIBM861"}), - new Charset("Cp862", "IBM862", new String[] {"862", "csPC862LatinHebrew"}), - new Charset("Cp863", "IBM863", new String[] {"863", "csIBM863"}), - new Charset("Cp864", "IBM864", new String[] {"cp864", "csIBM864"}), - new Charset("Cp865", "IBM865", new String[] {"865", "csIBM865"}), - new Charset("Cp866", "IBM866", new String[] {"866", "csIBM866"}), - new Charset("Cp868", "IBM868", new String[] {"cp-ar", "csIBM868"}), - new Charset("Cp869", "IBM869", new String[] {"cp-gr", "csIBM869"}), - new Charset("Cp870", "IBM870", new String[] {"ebcdic-cp-roece", "ebcdic-cp-yu", "csIBM870"}), - new Charset("Cp871", "IBM871", new String[] {"ebcdic-cp-is", "csIBM871"}), - new Charset("Cp918", "IBM918", new String[] {"ebcdic-cp-ar2", "csIBM918"}), - new Charset("Cp1026", "IBM1026", new String[] {"csIBM1026"}), - new Charset("Cp1047", "IBM1047", new String[] {"IBM-1047"}), - new Charset("Cp1140", "IBM01140", - new String[] {"CCSID01140", "CP01140", - "ebcdic-us-37+euro"}), - new Charset("Cp1141", "IBM01141", - new String[] {"CCSID01141", "CP01141", - "ebcdic-de-273+euro"}), - new Charset("Cp1142", "IBM01142", new String[] {"CCSID01142", "CP01142", "ebcdic-dk-277+euro", "ebcdic-no-277+euro"}), - new Charset("Cp1143", "IBM01143", new String[] {"CCSID01143", "CP01143", "ebcdic-fi-278+euro", "ebcdic-se-278+euro"}), - new Charset("Cp1144", "IBM01144", new String[] {"CCSID01144", "CP01144", "ebcdic-it-280+euro"}), - new Charset("Cp1145", "IBM01145", new String[] {"CCSID01145", "CP01145", "ebcdic-es-284+euro"}), - new Charset("Cp1146", "IBM01146", new String[] {"CCSID01146", "CP01146", "ebcdic-gb-285+euro"}), - new Charset("Cp1147", "IBM01147", new String[] {"CCSID01147", "CP01147", "ebcdic-fr-297+euro"}), - new Charset("Cp1148", "IBM01148", new String[] {"CCSID01148", "CP01148", "ebcdic-international-500+euro"}), - new Charset("Cp1149", "IBM01149", new String[] {"CCSID01149", "CP01149", "ebcdic-is-871+euro"}), - new Charset("Cp1250", "windows-1250", new String[] {}), - new Charset("Cp1251", "windows-1251", new String[] {}), - new Charset("Cp1252", "windows-1252", new String[] {}), - new Charset("Cp1253", "windows-1253", new String[] {}), - new Charset("Cp1254", "windows-1254", new String[] {}), - new Charset("Cp1255", "windows-1255", new String[] {}), - new Charset("Cp1256", "windows-1256", new String[] {}), - new Charset("Cp1257", "windows-1257", new String[] {}), - new Charset("Cp1258", "windows-1258", new String[] {}), - new Charset("ISO2022CN", "ISO-2022-CN", new String[] {}), - new Charset("ISO2022JP", "ISO-2022-JP", new String[] {"csISO2022JP", "JIS", "jis_encoding", "csjisencoding"}), - new Charset("ISO2022KR", "ISO-2022-KR", new String[] {"csISO2022KR"}), - new Charset("JIS_X0201", "JIS_X0201", new String[] {"X0201", "JIS0201", "csHalfWidthKatakana"}), - new Charset("JIS_X0212-1990", "JIS_X0212-1990", new String[] {"iso-ir-159", "x0212", "JIS0212", "csISO159JISX02121990"}), - new Charset("JIS_C6626-1983", "JIS_C6626-1983", new String[] {"x-JIS0208", "JIS0208", "csISO87JISX0208", "x0208", "JIS_X0208-1983", "iso-ir-87"}), - new Charset("SJIS", "Shift_JIS", new String[] {"MS_Kanji", "csShiftJIS", "shift-jis", "x-sjis", "pck"}), - new Charset("TIS620", "TIS-620", new String[] {}), - new Charset("MS932", "Windows-31J", new String[] {"windows-932", "csWindows31J", "x-ms-cp932"}), - new Charset("EUC_TW", "EUC-TW", new String[] {"x-EUC-TW", "cns11643", "euctw"}), - new Charset("x-Johab", "johab", new String[] {"johab", "cp1361", "ms1361", "ksc5601-1992", "ksc5601_1992"}), - new Charset("MS950_HKSCS", "", new String[] {}), - new Charset("MS874", "windows-874", new String[] {"cp874"}), - new Charset("MS949", "windows-949", new String[] {"windows949", "ms_949", "x-windows-949"}), - new Charset("MS950", "windows-950", new String[] {"x-windows-950"}), - - new Charset("Cp737", null, new String[] {}), - new Charset("Cp856", null, new String[] {}), - new Charset("Cp875", null, new String[] {}), - new Charset("Cp921", null, new String[] {}), - new Charset("Cp922", null, new String[] {}), - new Charset("Cp930", null, new String[] {}), - new Charset("Cp933", null, new String[] {}), - new Charset("Cp935", null, new String[] {}), - new Charset("Cp937", null, new String[] {}), - new Charset("Cp939", null, new String[] {}), - new Charset("Cp942", null, new String[] {}), - new Charset("Cp942C", null, new String[] {}), - new Charset("Cp943", null, new String[] {}), - new Charset("Cp943C", null, new String[] {}), - new Charset("Cp948", null, new String[] {}), - new Charset("Cp949", null, new String[] {}), - new Charset("Cp949C", null, new String[] {}), - new Charset("Cp950", null, new String[] {}), - new Charset("Cp964", null, new String[] {}), - new Charset("Cp970", null, new String[] {}), - new Charset("Cp1006", null, new String[] {}), - new Charset("Cp1025", null, new String[] {}), - new Charset("Cp1046", null, new String[] {}), - new Charset("Cp1097", null, new String[] {}), - new Charset("Cp1098", null, new String[] {}), - new Charset("Cp1112", null, new String[] {}), - new Charset("Cp1122", null, new String[] {}), - new Charset("Cp1123", null, new String[] {}), - new Charset("Cp1124", null, new String[] {}), - new Charset("Cp1381", null, new String[] {}), - new Charset("Cp1383", null, new String[] {}), - new Charset("Cp33722", null, new String[] {}), - new Charset("Big5_Solaris", null, new String[] {}), - new Charset("EUC_JP_LINUX", null, new String[] {}), - new Charset("EUC_JP_Solaris", null, new String[] {}), - new Charset("ISCII91", null, new String[] {"x-ISCII91", "iscii"}), - new Charset("ISO2022_CN_CNS", null, new String[] {}), - new Charset("ISO2022_CN_GB", null, new String[] {}), - new Charset("x-iso-8859-11", null, new String[] {}), - new Charset("JISAutoDetect", null, new String[] {}), - new Charset("MacArabic", null, new String[] {}), - new Charset("MacCentralEurope", null, new String[] {}), - new Charset("MacCroatian", null, new String[] {}), - new Charset("MacCyrillic", null, new String[] {}), - new Charset("MacDingbat", null, new String[] {}), - new Charset("MacGreek", "MacGreek", new String[] {}), - new Charset("MacHebrew", null, new String[] {}), - new Charset("MacIceland", null, new String[] {}), - new Charset("MacRoman", "MacRoman", new String[] {"Macintosh", "MAC", "csMacintosh"}), - new Charset("MacRomania", null, new String[] {}), - new Charset("MacSymbol", null, new String[] {}), - new Charset("MacThai", null, new String[] {}), - new Charset("MacTurkish", null, new String[] {}), - new Charset("MacUkraine", null, new String[] {}), - new Charset("UnicodeBig", null, new String[] {}), - new Charset("UnicodeLittle", null, new String[] {}) - }; - - /** - * Contains the canonical names of character sets which can be used to - * decode bytes into Java chars. - */ - private static TreeSet decodingSupported = null; - - /** - * Contains the canonical names of character sets which can be used to - * encode Java chars into bytes. - */ - private static TreeSet encodingSupported = null; - - /** - * Maps character set names to Charset objects. All possible names of - * a charset will be mapped to the Charset. - */ - private static HashMap charsetMap = null; - - static { - decodingSupported = new TreeSet(); - encodingSupported = new TreeSet(); - byte[] dummy = new byte[] {'d', 'u', 'm', 'm', 'y'}; - for (int i = 0; i < JAVA_CHARSETS.length; i++) { - try { - String s = new String(dummy, JAVA_CHARSETS[i].canonical); - decodingSupported.add(JAVA_CHARSETS[i].canonical.toLowerCase(Locale.US)); - } catch (UnsupportedOperationException e) { - } catch (UnsupportedEncodingException e) { - } - try { - "dummy".getBytes(JAVA_CHARSETS[i].canonical); - encodingSupported.add(JAVA_CHARSETS[i].canonical.toLowerCase(Locale.US)); - } catch (UnsupportedOperationException e) { - } catch (UnsupportedEncodingException e) { - } - } - - charsetMap = new HashMap(); - for (int i = 0; i < JAVA_CHARSETS.length; i++) { - Charset c = JAVA_CHARSETS[i]; - charsetMap.put(c.canonical.toLowerCase(Locale.US), c); - if (c.mime != null) { - charsetMap.put(c.mime.toLowerCase(Locale.US), c); - } - if (c.aliases != null) { - for (int j = 0; j < c.aliases.length; j++) { - charsetMap.put(c.aliases[j].toLowerCase(Locale.US), c); - } - } - } - - if (log.isDebugEnabled()) { - log.debug("Character sets which support decoding: " - + decodingSupported); - log.debug("Character sets which support encoding: " - + encodingSupported); - } - } - - /** - * ANDROID: THE FOLLOWING SET OF STATIC STRINGS ARE COPIED FROM A NEWER VERSION OF MIME4J - */ - - /** carriage return - line feed sequence */ - public static final String CRLF = "\r\n"; - - /** US-ASCII CR, carriage return (13) */ - public static final int CR = '\r'; - - /** US-ASCII LF, line feed (10) */ - public static final int LF = '\n'; - - /** US-ASCII SP, space (32) */ - public static final int SP = ' '; - - /** US-ASCII HT, horizontal-tab (9)*/ - public static final int HT = '\t'; - - public static final java.nio.charset.Charset US_ASCII = java.nio.charset.Charset - .forName("US-ASCII"); - - public static final java.nio.charset.Charset ISO_8859_1 = java.nio.charset.Charset - .forName("ISO-8859-1"); - - public static final java.nio.charset.Charset UTF_8 = java.nio.charset.Charset - .forName("UTF-8"); - - /** - * Returns true if the specified character is a whitespace - * character (CR, LF, SP or HT). - * - * ANDROID: COPIED FROM A NEWER VERSION OF MIME4J - * - * @param ch - * character to test. - * @return true if the specified character is a whitespace - * character, false otherwise. - */ - public static boolean isWhitespace(char ch) { - return ch == SP || ch == HT || ch == CR || ch == LF; - } - - /** - * Returns true if the specified string consists entirely of - * whitespace characters. - * - * ANDROID: COPIED FROM A NEWER VERSION OF MIME4J - * - * @param s - * string to test. - * @return true if the specified string consists entirely of - * whitespace characters, false otherwise. - */ - public static boolean isWhitespace(final String s) { - if (s == null) { - throw new IllegalArgumentException("String may not be null"); - } - final int len = s.length(); - for (int i = 0; i < len; i++) { - if (!isWhitespace(s.charAt(i))) { - return false; - } - } - return true; - } - - /** - * Determines if the VM supports encoding (chars to bytes) the - * specified character set. NOTE: the given character set name may - * not be known to the VM even if this method returns true. - * Use {@link #toJavaCharset(String)} to get the canonical Java character - * set name. - * - * @param charsetName the characters set name. - * @return true if encoding is supported, false - * otherwise. - */ - public static boolean isEncodingSupported(String charsetName) { - return encodingSupported.contains(charsetName.toLowerCase(Locale.US)); - } - - /** - * Determines if the VM supports decoding (bytes to chars) the - * specified character set. NOTE: the given character set name may - * not be known to the VM even if this method returns true. - * Use {@link #toJavaCharset(String)} to get the canonical Java character - * set name. - * - * @param charsetName the characters set name. - * @return true if decoding is supported, false - * otherwise. - */ - public static boolean isDecodingSupported(String charsetName) { - return decodingSupported.contains(charsetName.toLowerCase(Locale.US)); - } - - /** - * Gets the preferred MIME character set name for the specified - * character set or null if not known. - * - * @param charsetName the character set name to look for. - * @return the MIME preferred name or null if not known. - */ - public static String toMimeCharset(String charsetName) { - Charset c = charsetMap.get(charsetName.toLowerCase(Locale.US)); - if (c != null) { - return c.mime; - } - return null; - } - - /** - * Gets the canonical Java character set name for the specified - * character set or null if not known. This should be - * called before doing any conversions using the Java API. NOTE: - * you must use {@link #isEncodingSupported(String)} or - * {@link #isDecodingSupported(String)} to make sure the returned - * Java character set is supported by the current VM. - * - * @param charsetName the character set name to look for. - * @return the canonical Java name or null if not known. - */ - public static String toJavaCharset(String charsetName) { - Charset c = charsetMap.get(charsetName.toLowerCase(Locale.US)); - if (c != null) { - return c.canonical; - } - return null; - } - - public static java.nio.charset.Charset getCharset(String charsetName) { - String defaultCharset = "ISO-8859-1"; - - // Use the default chareset if given charset is null - if(charsetName == null) charsetName = defaultCharset; - - try { - return java.nio.charset.Charset.forName(charsetName); - } catch (IllegalCharsetNameException e) { - log.info("Illegal charset " + charsetName + ", fallback to " + - defaultCharset + ": " + e); - // Use default charset on exception - return java.nio.charset.Charset.forName(defaultCharset); - } catch (UnsupportedCharsetException ex) { - log.info("Unsupported charset " + charsetName + ", fallback to " + - defaultCharset + ": " + ex); - // Use default charset on exception - return java.nio.charset.Charset.forName(defaultCharset); - } - - } - /* - * Uncomment the code below and run the main method to regenerate the - * Javadoc table above when the known charsets change. - */ - - /* - private static String dumpHtmlTable() { - LinkedList l = new LinkedList(Arrays.asList(JAVA_CHARSETS)); - Collections.sort(l); - StringBuffer sb = new StringBuffer(); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - - for (Iterator it = l.iterator(); it.hasNext();) { - Charset c = (Charset) it.next(); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - sb.append(" * \n"); - } - sb.append(" *
Canonical (Java) nameMIME preferredAliases
" + c.canonical + "" + (c.mime == null ? "?" : c.mime)+ ""); - for (int i = 0; c.aliases != null && i < c.aliases.length; i++) { - sb.append(c.aliases[i] + " "); - } - sb.append("
\n"); - return sb.toString(); - } - - public static void main(String[] args) { - System.out.println(dumpHtmlTable()); - }*/ -} \ No newline at end of file diff --git a/assets/quantum/res/drawable-hdpi/quantum_ic_image_white_24.png b/assets/quantum/res/drawable-hdpi/quantum_ic_image_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..b414cf5b6881d6ec172d2a7fbd73ada5bbf167ab Binary files /dev/null and b/assets/quantum/res/drawable-hdpi/quantum_ic_image_white_24.png differ diff --git a/assets/quantum/res/drawable-mdpi/quantum_ic_image_white_24.png b/assets/quantum/res/drawable-mdpi/quantum_ic_image_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..d474bd577d00d2aa045685f38b1729e4b2c314e2 Binary files /dev/null and b/assets/quantum/res/drawable-mdpi/quantum_ic_image_white_24.png differ diff --git a/assets/quantum/res/drawable-xhdpi/quantum_ic_image_white_24.png b/assets/quantum/res/drawable-xhdpi/quantum_ic_image_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..2642b9e09ec00be308649f62d9323f22ae2b6c6c Binary files /dev/null and b/assets/quantum/res/drawable-xhdpi/quantum_ic_image_white_24.png differ diff --git a/assets/quantum/res/drawable-xxhdpi/quantum_ic_image_white_24.png b/assets/quantum/res/drawable-xxhdpi/quantum_ic_image_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f1defa6df89b5a7a68df6787a4ba799d3bd3b2 Binary files /dev/null and b/assets/quantum/res/drawable-xxhdpi/quantum_ic_image_white_24.png differ diff --git a/assets/quantum/res/drawable-xxxhdpi/quantum_ic_image_white_24.png b/assets/quantum/res/drawable-xxxhdpi/quantum_ic_image_white_24.png new file mode 100644 index 0000000000000000000000000000000000000000..2ffdb55f264ecd3610f90890f8202f93c00f72e1 Binary files /dev/null and b/assets/quantum/res/drawable-xxxhdpi/quantum_ic_image_white_24.png differ diff --git a/assets/quantum/res/drawable/quantum_ic_business_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_business_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..5fc1cef03045eae7e8cc5c9b6826ae0cf5e7c99a --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_business_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/assets/quantum/res/drawable/quantum_ic_enterprise_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_enterprise_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f1fd4920fcb1c68a7d3b6a03dcaaa01fa237b6b --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_enterprise_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/assets/quantum/res/drawable/quantum_ic_forward_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_forward_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce26499e7c4a6f81447a19a6d652f776a9f09d61 --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_forward_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/assets/quantum/res/drawable/quantum_ic_hd_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_hd_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..c67509cbfe0ceb16f90fda6b83f74076a4adacb3 --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_hd_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/assets/quantum/res/drawable/quantum_ic_network_wifi_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_network_wifi_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..495d9ce575853af7d0f6d845b7fd72831d575295 --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_network_wifi_vd_theme_24.xml @@ -0,0 +1,14 @@ + + + + diff --git a/assets/quantum/res/drawable/quantum_ic_report_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_report_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..d8544cb9b8a1843d0c99774dd4665f03c2ebe083 --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_report_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/assets/quantum/res/drawable/quantum_ic_voicemail_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_voicemail_vd_theme_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..d7e79d799336e884b359bb447ccb98eb151694ac --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_voicemail_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/java/com/android/contacts/common/AndroidManifest.xml b/java/com/android/contacts/common/AndroidManifest.xml index eae70cd30549a524a9139f180f8e353662f4f29f..e97221549cb17fc9753ba93c8ea9f7ae52016e27 100644 --- a/java/com/android/contacts/common/AndroidManifest.xml +++ b/java/com/android/contacts/common/AndroidManifest.xml @@ -26,14 +26,6 @@ - - - - - - diff --git a/java/com/android/contacts/common/ContactPhotoManager.java b/java/com/android/contacts/common/ContactPhotoManager.java index 9e627ae1f9a5d59feb9dca76b9c153e9843135e8..169348b25f17648fae2f56b96efc7bd5599efa76 100644 --- a/java/com/android/contacts/common/ContactPhotoManager.java +++ b/java/com/android/contacts/common/ContactPhotoManager.java @@ -39,6 +39,7 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { /** Contact type constants used for default letter images */ public static final int TYPE_PERSON = LetterTileDrawable.TYPE_PERSON; + public static final int TYPE_SPAM = LetterTileDrawable.TYPE_SPAM; public static final int TYPE_BUSINESS = LetterTileDrawable.TYPE_BUSINESS; public static final int TYPE_VOICEMAIL = LetterTileDrawable.TYPE_VOICEMAIL; public static final int TYPE_DEFAULT = LetterTileDrawable.TYPE_DEFAULT; @@ -190,7 +191,7 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { Context applicationContext = context.getApplicationContext(); sInstance = createContactPhotoManager(applicationContext); applicationContext.registerComponentCallbacks(sInstance); - if (PermissionsUtil.hasContactsPermissions(context)) { + if (PermissionsUtil.hasContactsReadPermissions(context)) { sInstance.preloadPhotosInBackground(); } } @@ -235,8 +236,13 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { loadThumbnail(view, photoId, darkTheme, isCircular, defaultImageRequest, DEFAULT_AVATAR); } - public final void loadDialerThumbnail( - QuickContactBadge badge, Uri contactUri, long photoId, String displayName, int contactType) { + public final void loadDialerThumbnailOrPhoto( + QuickContactBadge badge, + Uri contactUri, + long photoId, + Uri photoUri, + String displayName, + int contactType) { badge.assignContactUri(contactUri); badge.setOverlay(null); @@ -244,8 +250,11 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { ContactPhotoManager.DefaultImageRequest request = new ContactPhotoManager.DefaultImageRequest( displayName, lookupKey, contactType, true /* isCircular */); - loadThumbnail( - badge, photoId, false /* darkTheme */, true /* isCircular */, request, DEFAULT_AVATAR); + if (photoId == 0 && photoUri != null) { + loadDirectoryPhoto(badge, photoUri, false /* darkTheme */, true /* isCircular */, request); + } else { + loadThumbnail(badge, photoId, false /* darkTheme */, true /* isCircular */, request); + } } /** @@ -500,4 +509,3 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { } } } - diff --git a/java/com/android/contacts/common/compat/TelephonyManagerCompat.java b/java/com/android/contacts/common/compat/TelephonyManagerCompat.java index 84002256a2c2aef628a7327c1e9392a451264855..7e4803ca5e0cd15d162c6e1d581184f354a22ed4 100644 --- a/java/com/android/contacts/common/compat/TelephonyManagerCompat.java +++ b/java/com/android/contacts/common/compat/TelephonyManagerCompat.java @@ -41,6 +41,9 @@ public class TelephonyManagerCompat { public static final String EVENT_CALL_REMOTELY_UNHELD = "android.telecom.event.CALL_REMOTELY_UNHELD"; + public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC = + "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC"; + public static final String TELEPHONY_MANAGER_CLASS = "android.telephony.TelephonyManager"; private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE"; diff --git a/java/com/android/contacts/common/dialog/CallSubjectDialog.java b/java/com/android/contacts/common/dialog/CallSubjectDialog.java index 5e0d6b58a27ee6d2b0eacbb7d40c56ea3bfa5b64..0e793710282635c0831210256f489c8c48929d1e 100644 --- a/java/com/android/contacts/common/dialog/CallSubjectDialog.java +++ b/java/com/android/contacts/common/dialog/CallSubjectDialog.java @@ -47,8 +47,8 @@ import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.R; import com.android.contacts.common.compat.telecom.TelecomManagerCompat; import com.android.dialer.animation.AnimUtils; +import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; -import com.android.dialer.callintent.nano.CallInitiationType; import com.android.dialer.common.LogUtil; import com.android.dialer.util.ViewUtil; import java.nio.charset.Charset; @@ -65,7 +65,7 @@ public class CallSubjectDialog extends Activity { public static final String PREF_KEY_SUBJECT_HISTORY_ITEM = "subject_history_item"; /** Activity intent argument bundle keys: */ public static final String ARG_PHOTO_ID = "PHOTO_ID"; - + public static final String ARG_PHOTO_URI = "PHOTO_URI"; public static final String ARG_CONTACT_URI = "CONTACT_URI"; public static final String ARG_NAME_OR_NUMBER = "NAME_OR_NUMBER"; public static final String ARG_NUMBER = "NUMBER"; @@ -134,6 +134,7 @@ public class CallSubjectDialog extends Activity { }; private long mPhotoID; + private Uri mPhotoUri; private Uri mContactUri; private String mNameOrNumber; private String mNumber; @@ -195,6 +196,7 @@ public class CallSubjectDialog extends Activity { start( activity, -1 /* photoId */, + null /* photoUri */, null /* contactUri */, number /* nameOrNumber */, number /* number */, @@ -220,6 +222,7 @@ public class CallSubjectDialog extends Activity { public static void start( Activity activity, long photoId, + Uri photoUri, Uri contactUri, String nameOrNumber, String number, @@ -229,6 +232,7 @@ public class CallSubjectDialog extends Activity { PhoneAccountHandle phoneAccountHandle) { Bundle arguments = new Bundle(); arguments.putLong(ARG_PHOTO_ID, photoId); + arguments.putParcelable(ARG_PHOTO_URI, photoUri); arguments.putParcelable(ARG_CONTACT_URI, contactUri); arguments.putString(ARG_NAME_OR_NUMBER, nameOrNumber); arguments.putString(ARG_NUMBER, number); @@ -320,15 +324,18 @@ public class CallSubjectDialog extends Activity { private void updateContactInfo() { if (mContactUri != null) { ContactPhotoManager.getInstance(this) - .loadDialerThumbnail(mContactPhoto, mContactUri, mPhotoID, mNameOrNumber, mContactType); + .loadDialerThumbnailOrPhoto( + mContactPhoto, mContactUri, mPhotoID, mPhotoUri, mNameOrNumber, mContactType); } else { mContactPhoto.setVisibility(View.GONE); } mNameView.setText(mNameOrNumber); - if (!TextUtils.isEmpty(mNumberLabel) && !TextUtils.isEmpty(mDisplayNumber)) { + if (!TextUtils.isEmpty(mDisplayNumber)) { mNumberView.setVisibility(View.VISIBLE); mNumberView.setText( - getString(R.string.call_subject_type_and_number, mNumberLabel, mDisplayNumber)); + TextUtils.isEmpty(mNumberLabel) + ? mDisplayNumber + : getString(R.string.call_subject_type_and_number, mNumberLabel, mDisplayNumber)); } else { mNumberView.setVisibility(View.GONE); mNumberView.setText(null); @@ -343,6 +350,7 @@ public class CallSubjectDialog extends Activity { return; } mPhotoID = arguments.getLong(ARG_PHOTO_ID); + mPhotoUri = arguments.getParcelable(ARG_PHOTO_URI); mContactUri = arguments.getParcelable(ARG_CONTACT_URI); mNameOrNumber = arguments.getString(ARG_NAME_OR_NUMBER); mNumber = arguments.getString(ARG_NUMBER); diff --git a/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java b/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java index e96496cdaf2496f4ba126bb024e4d539ae97dec2..751490a22c57329272f6c4ff60000775e1070de8 100644 --- a/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java +++ b/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java @@ -48,7 +48,7 @@ public class ClearFrequentsDialog extends DialogFragment { new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - if (!PermissionsUtil.hasContactsPermissions(context)) { + if (!PermissionsUtil.hasContactsReadPermissions(context)) { return; } diff --git a/java/com/android/contacts/common/lettertiles/LetterTileDrawable.java b/java/com/android/contacts/common/lettertiles/LetterTileDrawable.java index ca12f18127b1f108aa806609adec3b49bf2f51d0..f8ea140b35103ac4681d96c5d0fc48b581c1e849 100644 --- a/java/com/android/contacts/common/lettertiles/LetterTileDrawable.java +++ b/java/com/android/contacts/common/lettertiles/LetterTileDrawable.java @@ -20,7 +20,6 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; @@ -49,7 +48,7 @@ public class LetterTileDrawable extends Drawable { * #TYPE_BUSINESS}, and voicemail contacts should use {@link #TYPE_VOICEMAIL}. */ @Retention(RetentionPolicy.SOURCE) - @IntDef({TYPE_PERSON, TYPE_BUSINESS, TYPE_VOICEMAIL, TYPE_GENERIC_AVATAR}) + @IntDef({TYPE_PERSON, TYPE_BUSINESS, TYPE_VOICEMAIL, TYPE_GENERIC_AVATAR, TYPE_SPAM}) public @interface ContactType {} /** Contact type constants */ @@ -61,6 +60,7 @@ public class LetterTileDrawable extends Drawable { * situations where a contact is anonymous. */ public static final int TYPE_GENERIC_AVATAR = 4; + public static final int TYPE_SPAM = 5; @ContactType public static final int TYPE_DEFAULT = TYPE_PERSON; /** @@ -78,6 +78,10 @@ public class LetterTileDrawable extends Drawable { /** 54% opacity */ private static final int ALPHA = 138; + /** 100% opacity */ + private static final int SPAM_ALPHA = 255; + /** Default icon scale for vector drawable. */ + private static final float VECTOR_ICON_SCALE = 0.7f; /** Reusable components to avoid new allocations */ private static final Paint sPaint = new Paint(); @@ -87,14 +91,16 @@ public class LetterTileDrawable extends Drawable { /** Letter tile */ private static TypedArray sColors; + private static int sSpamColor; private static int sDefaultColor; private static int sTileFontColor; private static float sLetterToTileRatio; - private static Bitmap sDefaultPersonAvatar; - private static Bitmap sDefaultBusinessAvatar; - private static Bitmap sDefaultVoicemailAvatar; + private static Drawable sDefaultPersonAvatar; + private static Drawable sDefaultBusinessAvatar; + private static Drawable sDefaultVoicemailAvatar; + private static Drawable sDefaultSpamAvatar; private final Paint mPaint; - private int mContactType = TYPE_DEFAULT; + @ContactType private int mContactType = TYPE_DEFAULT; private float mScale = 1.0f; private float mOffset = 0.0f; private boolean mIsCircle = false; @@ -102,21 +108,20 @@ public class LetterTileDrawable extends Drawable { private int mColor; private Character mLetter = null; - @ContactType private int mAvatarType = TYPE_DEFAULT; private String mDisplayName; public LetterTileDrawable(final Resources res) { if (sColors == null) { sColors = res.obtainTypedArray(R.array.letter_tile_colors); + sSpamColor = res.getColor(R.color.spam_contact_background); sDefaultColor = res.getColor(R.color.letter_tile_default_color); sTileFontColor = res.getColor(R.color.letter_tile_font_color); sLetterToTileRatio = res.getFraction(R.dimen.letter_to_tile_ratio, 1, 1); sDefaultPersonAvatar = - BitmapFactory.decodeResource( - res, R.drawable.product_logo_avatar_anonymous_white_color_120); - sDefaultBusinessAvatar = - BitmapFactory.decodeResource(res, R.drawable.ic_business_white_120dp); - sDefaultVoicemailAvatar = BitmapFactory.decodeResource(res, R.drawable.ic_voicemail_avatar); + res.getDrawable(R.drawable.product_logo_avatar_anonymous_white_color_120, null); + sDefaultBusinessAvatar = res.getDrawable(R.drawable.quantum_ic_business_vd_theme_24, null); + sDefaultVoicemailAvatar = res.getDrawable(R.drawable.quantum_ic_voicemail_vd_theme_24, null); + sDefaultSpamAvatar = res.getDrawable(R.drawable.quantum_ic_report_vd_theme_24, null); sPaint.setTypeface( Typeface.create(res.getString(R.string.letter_tile_letter_font_family), Typeface.NORMAL)); sPaint.setTextAlign(Align.CENTER); @@ -128,12 +133,32 @@ public class LetterTileDrawable extends Drawable { mColor = sDefaultColor; } - private static Bitmap getBitmapForContactType(int contactType) { + private Rect getScaledBounds(float scale, float offset) { + // The drawable should be drawn in the middle of the canvas without changing its width to + // height ratio. + final Rect destRect = copyBounds(); + // Crop the destination bounds into a square, scaled and offset as appropriate + final int halfLength = (int) (scale * Math.min(destRect.width(), destRect.height()) / 2); + + destRect.set( + destRect.centerX() - halfLength, + (int) (destRect.centerY() - halfLength + offset * destRect.height()), + destRect.centerX() + halfLength, + (int) (destRect.centerY() + halfLength + offset * destRect.height())); + return destRect; + } + + private Drawable getDrawableForContactType(int contactType) { switch (contactType) { case TYPE_BUSINESS: + mScale = VECTOR_ICON_SCALE; return sDefaultBusinessAvatar; case TYPE_VOICEMAIL: + mScale = VECTOR_ICON_SCALE; return sDefaultVoicemailAvatar; + case TYPE_SPAM: + mScale = VECTOR_ICON_SCALE; + return sDefaultSpamAvatar; case TYPE_PERSON: case TYPE_GENERIC_AVATAR: default: @@ -163,39 +188,11 @@ public class LetterTileDrawable extends Drawable { return bitmap; } - /** - * Draw the bitmap onto the canvas at the current bounds taking into account the current scale. - */ - private void drawBitmap( - final Bitmap bitmap, final int width, final int height, final Canvas canvas) { - // The bitmap should be drawn in the middle of the canvas without changing its width to - // height ratio. - final Rect destRect = copyBounds(); - - // Crop the destination bounds into a square, scaled and offset as appropriate - final int halfLength = (int) (mScale * Math.min(destRect.width(), destRect.height()) / 2); - - destRect.set( - destRect.centerX() - halfLength, - (int) (destRect.centerY() - halfLength + mOffset * destRect.height()), - destRect.centerX() + halfLength, - (int) (destRect.centerY() + halfLength + mOffset * destRect.height())); - - // Source rectangle remains the entire bounds of the source bitmap. - sRect.set(0, 0, width, height); - - sPaint.setTextAlign(Align.CENTER); - sPaint.setAntiAlias(true); - sPaint.setAlpha(ALPHA); - - canvas.drawBitmap(bitmap, sRect, destRect, sPaint); - } - private void drawLetterTile(final Canvas canvas) { // Draw background color. sPaint.setColor(mColor); - sPaint.setAlpha(mPaint.getAlpha()); + final Rect bounds = getBounds(); final int minDimension = Math.min(bounds.width(), bounds.height()); @@ -206,7 +203,6 @@ public class LetterTileDrawable extends Drawable { } // Draw letter/digit only if the first character is an english letter or there's a override - if (mLetter != null) { // Draw letter or digit. sFirstChar[0] = mLetter; @@ -229,8 +225,10 @@ public class LetterTileDrawable extends Drawable { sPaint); } else { // Draw the default image if there is no letter/digit to be drawn - final Bitmap bitmap = getBitmapForContactType(mContactType); - drawBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), canvas); + Drawable drawable = getDrawableForContactType(mContactType); + drawable.setBounds(getScaledBounds(mScale, mOffset)); + drawable.setAlpha(drawable == sDefaultSpamAvatar ? SPAM_ALPHA : ALPHA); + drawable.draw(canvas); } } @@ -245,11 +243,16 @@ public class LetterTileDrawable extends Drawable { /** Returns a deterministic color based on the provided contact identifier string. */ private int pickColor(final String identifier) { + if (mContactType == TYPE_SPAM) { + return sSpamColor; + } + if (mContactType == TYPE_VOICEMAIL || mContactType == TYPE_BUSINESS || TextUtils.isEmpty(identifier)) { return sDefaultColor; } + // String.hashCode() implementation is not supposed to change across java versions, so // this should guarantee the same email address always maps to the same color. // The email should already have been normalized by the ContactRequest. @@ -321,7 +324,7 @@ public class LetterTileDrawable extends Drawable { private LetterTileDrawable setLetterAndColorFromContactDetails( final String displayName, final String identifier) { - if (displayName != null && displayName.length() > 0 && isEnglishLetter(displayName.charAt(0))) { + if (!TextUtils.isEmpty(displayName) && isEnglishLetter(displayName.charAt(0))) { mLetter = Character.toUpperCase(displayName.charAt(0)); } else { mLetter = null; @@ -382,11 +385,10 @@ public class LetterTileDrawable extends Drawable { } this.mDisplayName = displayName; - this.mAvatarType = contactType; - setContactType(this.mAvatarType); + setContactType(contactType); // Special contact types receive default color and no letter tile, but special iconography. - if (this.mAvatarType != TYPE_PERSON) { + if (contactType != TYPE_PERSON) { this.setLetterAndColorFromContactDetails(null, null); } else { if (identifierForTileColor != null) { diff --git a/java/com/android/contacts/common/list/ContactListItemView.java b/java/com/android/contacts/common/list/ContactListItemView.java index 76842483a9feac47d6dcd6a80445ce46a43d25b7..7a319472053091aa531e0b7768d46fbf82bd3938 100644 --- a/java/com/android/contacts/common/list/ContactListItemView.java +++ b/java/com/android/contacts/common/list/ContactListItemView.java @@ -29,6 +29,7 @@ import android.os.Bundle; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.SearchSnippets; +import android.support.annotation.IntDef; import android.support.v4.content.ContextCompat; import android.support.v4.graphics.drawable.DrawableCompat; import android.text.Spannable; @@ -51,10 +52,13 @@ import com.android.contacts.common.ContactStatusUtil; import com.android.contacts.common.R; import com.android.contacts.common.compat.PhoneNumberUtilsCompat; import com.android.contacts.common.format.TextHighlighter; +import com.android.contacts.common.list.PhoneNumberListAdapter.Listener; import com.android.contacts.common.util.ContactDisplayUtils; import com.android.contacts.common.util.SearchUtil; import com.android.dialer.compat.CompatUtils; import com.android.dialer.util.ViewUtil; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -74,6 +78,16 @@ import java.util.regex.Pattern; * contact's data and a divider between contact view. */ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdjuster { + + /** IntDef for indices of ViewPager tabs. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({NONE, VIDEO, CALL_AND_SHARE}) + public @interface CallToAction {} + + public static final int NONE = 0; + public static final int VIDEO = 1; + public static final int CALL_AND_SHARE = 2; + private static final Pattern SPLIT_PATTERN = Pattern.compile("([\\w-\\.]+)@((?:[\\w]+\\.)+)([a-zA-Z]{2,4})|[\\w]+"); static final char SNIPPET_START_MATCH = '['; @@ -92,8 +106,8 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj private int mNameTextViewTextSize; private int mHeaderWidth; private Drawable mActivatedBackgroundDrawable; - private int mVideoCallIconSize = 32; - private int mVideoCallIconMargin = 16; + private int mCallToActionSize = 32; + private int mCallToActionMargin = 16; // Set in onLayout. Represent left and right position of the View on the screen. private int mLeftOffset; private int mRightOffset; @@ -106,12 +120,10 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj private ArrayList mNumberHighlightSequence; // Highlighting prefix for names. private String mHighlightedPrefix; - /** Used to notify listeners when a video call icon is clicked. */ - private PhoneNumberListAdapter.Listener mPhoneNumberListAdapterListener; - /** Indicates whether to show the "video call" icon, used to initiate a video call. */ - private boolean mShowVideoCallIcon = false; /** Indicates whether the view should leave room for the "video call" icon. */ - private boolean mSupportVideoCallIcon = false; + private boolean mSupportVideoCall; + /** Indicates whether the view should leave room for the "call and share" icon. */ + private boolean mSupportCallAndShare; private PhotoPosition mPhotoPosition = getDefaultPhotoPosition(false /* normal/non opposite */); // Header layout data @@ -127,7 +139,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj private TextView mSnippetView; private TextView mStatusView; private ImageView mPresenceIcon; - private ImageView mVideoCallIcon; + private ImageView mCallToAction; private ImageView mWorkProfileIcon; private ColorStateList mSecondaryTextColor; private int mDefaultPhotoViewSize = 0; @@ -168,20 +180,24 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj private boolean mAdjustSelectionBoundsEnabled = true; private Rect mBoundsWithoutHeader = new Rect(); private CharSequence mUnknownNameText; - private int mPosition; public ContactListItemView(Context context) { super(context); mTextHighlighter = new TextHighlighter(Typeface.BOLD); - mNameHighlightSequence = new ArrayList(); - mNumberHighlightSequence = new ArrayList(); + mNameHighlightSequence = new ArrayList<>(); + mNumberHighlightSequence = new ArrayList<>(); } - public ContactListItemView(Context context, AttributeSet attrs, boolean supportVideoCallIcon) { + public ContactListItemView( + Context context, + AttributeSet attrs, + boolean supportVideoCallIcon, + boolean supportCallAndShare) { this(context, attrs); - mSupportVideoCallIcon = supportVideoCallIcon; + mSupportVideoCall = supportVideoCallIcon; + mSupportCallAndShare = supportCallAndShare; } public ContactListItemView(Context context, AttributeSet attrs) { @@ -197,7 +213,6 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj R.styleable.ContactListItemView_list_item_height, mPreferredHeight); mActivatedBackgroundDrawable = a.getDrawable(R.styleable.ContactListItemView_activated_background); - mGapBetweenImageAndText = a.getDimensionPixelOffset( R.styleable.ContactListItemView_list_item_gap_between_image_and_text, @@ -235,13 +250,13 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj a.getDimension( R.styleable.ContactListItemView_list_item_name_text_size, (int) getResources().getDimension(R.dimen.contact_browser_list_item_text_size)); - mVideoCallIconSize = + mCallToActionSize = a.getDimensionPixelOffset( - R.styleable.ContactListItemView_list_item_video_call_icon_size, mVideoCallIconSize); - mVideoCallIconMargin = + R.styleable.ContactListItemView_list_item_video_call_icon_size, mCallToActionSize); + mCallToActionMargin = a.getDimensionPixelOffset( R.styleable.ContactListItemView_list_item_video_call_icon_margin, - mVideoCallIconMargin); + mCallToActionMargin); setPaddingRelative( a.getDimensionPixelOffset(R.styleable.ContactListItemView_list_item_padding_left, 0), @@ -266,13 +281,13 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj mActivatedBackgroundDrawable.setCallback(this); } - mNameHighlightSequence = new ArrayList(); - mNumberHighlightSequence = new ArrayList(); + mNameHighlightSequence = new ArrayList<>(); + mNumberHighlightSequence = new ArrayList<>(); setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE); } - public static final PhotoPosition getDefaultPhotoPosition(boolean opposite) { + public static PhotoPosition getDefaultPhotoPosition(boolean opposite) { final Locale locale = Locale.getDefault(); final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale); switch (layoutDirection) { @@ -310,45 +325,43 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj } /** - * Sets whether the video calling icon is shown. For the video calling icon to be shown, {@link - * #mSupportVideoCallIcon} must be {@code true}. + * Sets whether the call to action is shown. For the {@link CallToAction} to be shown, it must be + * supported as well. * - * @param showVideoCallIcon {@code true} if the video calling icon is shown, {@code false} - * otherwise. - * @param listener Listener to notify when the video calling icon is clicked. - * @param position The position in the adapater of the video calling icon. + * @param action {@link CallToAction} you want to display (if it's supported). + * @param listener Listener to notify when the call to action is clicked. + * @param position The position in the adapter of the call to action. */ - public void setShowVideoCallIcon( - boolean showVideoCallIcon, PhoneNumberListAdapter.Listener listener, int position) { - mShowVideoCallIcon = showVideoCallIcon; - mPhoneNumberListAdapterListener = listener; - mPosition = position; - - if (mShowVideoCallIcon) { - if (mVideoCallIcon == null) { - mVideoCallIcon = new ImageView(getContext()); - addView(mVideoCallIcon); - } - mVideoCallIcon.setContentDescription( - getContext().getString(R.string.description_search_video_call)); - mVideoCallIcon.setImageResource(R.drawable.ic_search_video_call); - mVideoCallIcon.setScaleType(ScaleType.CENTER); - mVideoCallIcon.setVisibility(View.VISIBLE); - mVideoCallIcon.setOnClickListener( - new OnClickListener() { - @Override - public void onClick(View v) { - // Inform the adapter that the video calling icon was clicked. - if (mPhoneNumberListAdapterListener != null) { - mPhoneNumberListAdapterListener.onVideoCallIconClicked(mPosition); - } - } - }); + public void setCallToAction(@CallToAction int action, Listener listener, int position) { + int drawable; + int description; + OnClickListener onClickListener; + if (action == CALL_AND_SHARE && mSupportCallAndShare) { + drawable = R.drawable.ic_call_and_share; + description = R.string.description_search_video_call; + onClickListener = v -> listener.onCallAndShareIconClicked(position); + } else if (action == VIDEO && mSupportVideoCall) { + drawable = R.drawable.ic_search_video_call; + description = R.string.description_search_call_and_share; + onClickListener = v -> listener.onVideoCallIconClicked(position); } else { - if (mVideoCallIcon != null) { - mVideoCallIcon.setVisibility(View.GONE); + if (mCallToAction != null) { + mCallToAction.setVisibility(View.GONE); + mCallToAction.setOnClickListener(null); } + return; } + + if (mCallToAction == null) { + mCallToAction = new ImageView(getContext()); + mCallToAction.setLayoutParams(new LayoutParams(mCallToActionSize, mCallToActionSize)); + mCallToAction.setScaleType(ScaleType.CENTER); + addView(mCallToAction); + } + mCallToAction.setContentDescription(getContext().getString(description)); + mCallToAction.setOnClickListener(onClickListener); + mCallToAction.setImageResource(drawable); + mCallToAction.setVisibility(View.VISIBLE); } /** @@ -356,11 +369,23 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj * actually showing an icon. Support for the video calling icon ensures that the layout leaves * space for the video icon, should it be shown. * - * @param supportVideoCallIcon {@code true} if the video call icon is supported, {@code false} + * @param supportVideoCall {@code true} if the video call icon is supported, {@code false} + * otherwise. + */ + public void setSupportVideoCallIcon(boolean supportVideoCall) { + mSupportVideoCall = supportVideoCall; + } + + /** + * Sets whether the view supports a call and share icon. This is independent of whether the view + * is actually showing an icon. Support for the icon ensures that the layout leaves space for it, + * should it be shown. + * + * @param supportCallAndShare {@code true} if the call and share icon is supported, {@code false} * otherwise. */ - public void setSupportVideoCallIcon(boolean supportVideoCallIcon) { - mSupportVideoCallIcon = supportVideoCallIcon; + public void setSupportCallAndShareIcon(boolean supportCallAndShare) { + mSupportCallAndShare = supportCallAndShare; } @Override @@ -398,8 +423,8 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj effectiveWidth -= mHeaderWidth + mGapBetweenImageAndText; } - if (mSupportVideoCallIcon) { - effectiveWidth -= (mVideoCallIconSize + mVideoCallIconMargin); + if (mSupportVideoCall || mSupportCallAndShare) { + effectiveWidth -= (mCallToActionSize + mCallToActionMargin); } // Go over all visible text views and measure actual width of each of them. @@ -471,10 +496,10 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj mStatusTextViewHeight = mPresenceIcon.getMeasuredHeight(); } - if (mSupportVideoCallIcon && isVisible(mVideoCallIcon)) { - mVideoCallIcon.measure( - MeasureSpec.makeMeasureSpec(mVideoCallIconSize, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(mVideoCallIconSize, MeasureSpec.EXACTLY)); + if ((mSupportVideoCall || mSupportCallAndShare) && isVisible(mCallToAction)) { + mCallToAction.measure( + MeasureSpec.makeMeasureSpec(mCallToActionSize, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(mCallToActionSize, MeasureSpec.EXACTLY)); } if (isVisible(mWorkProfileIcon)) { @@ -529,7 +554,6 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj // Determine the vertical bounds by laying out the header first. int topBound = 0; - int bottomBound = height; int leftBound = getPaddingLeft(); int rightBound = width - getPaddingRight(); @@ -545,7 +569,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj } if (mHeaderTextView != null) { int headerHeight = mHeaderTextView.getMeasuredHeight(); - int headerTopBound = (bottomBound + topBound - headerHeight) / 2 + mTextOffsetTop; + int headerTopBound = (height + topBound - headerHeight) / 2 + mTextOffsetTop; mHeaderTextView.layout( isLayoutRtl ? rightBound - mHeaderWidth : leftBound, @@ -560,7 +584,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj } } - mBoundsWithoutHeader.set(left + leftBound, topBound, left + rightBound, bottomBound); + mBoundsWithoutHeader.set(left + leftBound, topBound, left + rightBound, height); mLeftOffset = left + leftBound; mRightOffset = left + rightBound; if (mIsSectionHeaderEnabled) { @@ -580,7 +604,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj // Photo is the left most view. All the other Views should on the right of the photo. if (photoView != null) { // Center the photo vertically - final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; + final int photoTop = topBound + (height - topBound - mPhotoViewHeight) / 2; photoView.layout( leftBound, photoTop, leftBound + mPhotoViewWidth, photoTop + mPhotoViewHeight); leftBound += mPhotoViewWidth + mGapBetweenImageAndText; @@ -592,7 +616,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj // Photo is the right most view. Right bound should be adjusted that way. if (photoView != null) { // Center the photo vertically - final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; + final int photoTop = topBound + (height - topBound - mPhotoViewHeight) / 2; photoView.layout( rightBound - mPhotoViewWidth, photoTop, rightBound, photoTop + mPhotoViewHeight); rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); @@ -605,33 +629,33 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj leftBound += mTextIndent; } - if (mSupportVideoCallIcon) { - // Place the video call button at the end of the list (e.g. take into account RTL mode). - if (isVisible(mVideoCallIcon)) { - // Center the video icon vertically - final int videoIconTop = topBound + (bottomBound - topBound - mVideoCallIconSize) / 2; + if (mSupportVideoCall || mSupportCallAndShare) { + // Place the call to action at the end of the list (e.g. take into account RTL mode). + if (isVisible(mCallToAction)) { + // Center the icon vertically + final int callToActionTop = topBound + (height - topBound - mCallToActionSize) / 2; if (!isLayoutRtl) { - // When photo is on left, video icon is placed on the right edge. - mVideoCallIcon.layout( - rightBound - mVideoCallIconSize, - videoIconTop, + // When photo is on left, icon is placed on the right edge. + mCallToAction.layout( + rightBound - mCallToActionSize, + callToActionTop, rightBound, - videoIconTop + mVideoCallIconSize); + callToActionTop + mCallToActionSize); } else { - // When photo is on right, video icon is placed on the left edge. - mVideoCallIcon.layout( + // When photo is on right, icon is placed on the left edge. + mCallToAction.layout( leftBound, - videoIconTop, - leftBound + mVideoCallIconSize, - videoIconTop + mVideoCallIconSize); + callToActionTop, + leftBound + mCallToActionSize, + callToActionTop + mCallToActionSize); } } if (mPhotoPosition == PhotoPosition.LEFT) { - rightBound -= (mVideoCallIconSize + mVideoCallIconMargin); + rightBound -= (mCallToActionSize + mCallToActionMargin); } else { - leftBound += mVideoCallIconSize + mVideoCallIconMargin; + leftBound += mCallToActionSize + mCallToActionMargin; } } @@ -642,7 +666,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj + mLabelAndDataViewMaxHeight + mSnippetTextViewHeight + mStatusTextViewHeight; - int textTopBound = (bottomBound + topBound - totalTextHeight) / 2 + mTextOffsetTop; + int textTopBound = (height + topBound - totalTextHeight) / 2 + mTextOffsetTop; // Work Profile icon align top int workProfileIconWidth = 0; @@ -854,7 +878,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj if (!TextUtils.isEmpty(title)) { if (mHeaderTextView == null) { mHeaderTextView = new TextView(getContext()); - mHeaderTextView.setTextAppearance(getContext(), R.style.SectionHeaderStyle); + mHeaderTextView.setTextAppearance(R.style.SectionHeaderStyle); mHeaderTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL); addView(mHeaderTextView); } @@ -1014,7 +1038,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj mLabelView.setSingleLine(true); mLabelView.setEllipsize(getTextEllipsis()); - mLabelView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); + mLabelView.setTextAppearance(R.style.TextAppearanceSmall); if (mPhotoPosition == PhotoPosition.LEFT) { mLabelView.setAllCaps(true); } else { @@ -1081,7 +1105,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj mDataView = new TextView(getContext()); mDataView.setSingleLine(true); mDataView.setEllipsize(getTextEllipsis()); - mDataView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); + mDataView.setTextAppearance(R.style.TextAppearanceSmall); mDataView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); mDataView.setActivated(isActivated()); mDataView.setId(R.id.cliv_data_view); @@ -1117,7 +1141,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj mSnippetView = new TextView(getContext()); mSnippetView.setSingleLine(true); mSnippetView.setEllipsize(getTextEllipsis()); - mSnippetView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); + mSnippetView.setTextAppearance(android.R.style.TextAppearance_Small); mSnippetView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); mSnippetView.setActivated(isActivated()); addView(mSnippetView); @@ -1131,7 +1155,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj mStatusView = new TextView(getContext()); mStatusView.setSingleLine(true); mStatusView.setEllipsize(getTextEllipsis()); - mStatusView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); + mStatusView.setTextAppearance(android.R.style.TextAppearance_Small); mStatusView.setTextColor(mSecondaryTextColor); mStatusView.setActivated(isActivated()); mStatusView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); @@ -1483,7 +1507,7 @@ public class ContactListItemView extends ViewGroup implements SelectionBoundsAdj } } - private final boolean pointIsInView(float localX, float localY) { + private boolean pointIsInView(float localX, float localY) { return localX >= mLeftOffset && localX < mRightOffset && localY >= 0 diff --git a/java/com/android/contacts/common/list/DirectoryListLoader.java b/java/com/android/contacts/common/list/DirectoryListLoader.java index 48b098c076006fd94c39cd1ccd1d89a0335b7ec1..be62cc7a83fb154ac84fa979133376db6d339b13 100644 --- a/java/com/android/contacts/common/list/DirectoryListLoader.java +++ b/java/com/android/contacts/common/list/DirectoryListLoader.java @@ -25,9 +25,10 @@ import android.net.Uri; import android.os.Handler; import android.provider.ContactsContract.Directory; import android.text.TextUtils; -import android.util.Log; import com.android.contacts.common.R; import com.android.contacts.common.compat.DirectoryCompat; +import com.android.dialer.common.LogUtil; +import com.android.dialer.util.PermissionsUtil; /** A specialized loader for the list of directories, see {@link Directory}. */ public class DirectoryListLoader extends AsyncTaskLoader { @@ -38,7 +39,6 @@ public class DirectoryListLoader extends AsyncTaskLoader { public static final int SEARCH_MODE_DATA_SHORTCUT = 3; // This is a virtual column created for a MatrixCursor. public static final String DIRECTORY_TYPE = "directoryType"; - private static final String TAG = "ContactEntryListAdapter"; private static final String[] RESULT_PROJECTION = { Directory._ID, DIRECTORY_TYPE, Directory.DISPLAY_NAME, Directory.PHOTO_SUPPORT, }; @@ -71,7 +71,13 @@ public class DirectoryListLoader extends AsyncTaskLoader { @Override protected void onStartLoading() { - getContext().getContentResolver().registerContentObserver(DirectoryQuery.URI, false, mObserver); + if (PermissionsUtil.hasContactsReadPermissions(getContext())) { + getContext() + .getContentResolver() + .registerContentObserver(DirectoryQuery.URI, false, mObserver); + } else { + LogUtil.w("DirectoryListLoader.onStartLoading", "contacts permission not available."); + } forceLoad(); } @@ -141,7 +147,9 @@ public class DirectoryListLoader extends AsyncTaskLoader { try { directoryType = pm.getResourcesForApplication(packageName).getString(typeResourceId); } catch (Exception e) { - Log.e(TAG, "Cannot obtain directory type from package: " + packageName); + LogUtil.e( + "ContactEntryListAdapter.loadInBackground", + "cannot obtain directory type from package: " + packageName); } } String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME); @@ -149,7 +157,8 @@ public class DirectoryListLoader extends AsyncTaskLoader { result.addRow(new Object[] {directoryId, directoryType, displayName, photoSupport}); } } catch (RuntimeException e) { - Log.w(TAG, "Runtime Exception when querying directory"); + LogUtil.w( + "ContactEntryListAdapter.loadInBackground", "runtime exception when querying directory"); } finally { if (cursor != null) { cursor.close(); diff --git a/java/com/android/contacts/common/list/OnPhoneNumberPickerActionListener.java b/java/com/android/contacts/common/list/OnPhoneNumberPickerActionListener.java index 89bd889e6377309f1ed173ccff64783e63124d61..c75e0a730023ef8752f5b49b07f5d808fd71ed63 100644 --- a/java/com/android/contacts/common/list/OnPhoneNumberPickerActionListener.java +++ b/java/com/android/contacts/common/list/OnPhoneNumberPickerActionListener.java @@ -17,13 +17,11 @@ package com.android.contacts.common.list; import android.app.ActionBar; import android.net.Uri; -import com.android.dialer.callintent.nano.CallSpecificAppData; +import com.android.dialer.callintent.CallSpecificAppData; /** Action callbacks that can be sent by a phone number picker. */ public interface OnPhoneNumberPickerActionListener { - int CALL_INITIATION_UNKNOWN = 0; - /** Returns the selected phone number uri to the requester. */ void onPickDataUri(Uri dataUri, boolean isVideoCall, CallSpecificAppData callSpecificAppData); diff --git a/java/com/android/contacts/common/list/PhoneNumberListAdapter.java b/java/com/android/contacts/common/list/PhoneNumberListAdapter.java index c7b24229f93c113f5a28a3bd5d4adcf941f5343e..9a490d78a8a3ac0c57527359b6edb30b3ebc2d3a 100644 --- a/java/com/android/contacts/common/list/PhoneNumberListAdapter.java +++ b/java/com/android/contacts/common/list/PhoneNumberListAdapter.java @@ -28,20 +28,26 @@ import android.provider.ContactsContract.CommonDataKinds.SipAddress; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Directory; import android.text.TextUtils; -import android.util.Log; import android.view.View; import android.view.ViewGroup; +import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; import com.android.contacts.common.ContactsUtils; -import com.android.contacts.common.GeoUtil; import com.android.contacts.common.R; import com.android.contacts.common.compat.CallableCompat; import com.android.contacts.common.compat.DirectoryCompat; import com.android.contacts.common.compat.PhoneCompat; import com.android.contacts.common.extensions.PhoneDirectoryExtenderAccessor; +import com.android.contacts.common.list.ContactListItemView.CallToAction; import com.android.contacts.common.preference.ContactsPreferences; import com.android.contacts.common.util.Constants; +import com.android.dialer.callcomposer.CallComposerContact; +import com.android.dialer.common.LogUtil; import com.android.dialer.compat.CompatUtils; +import com.android.dialer.enrichedcall.EnrichedCallCapabilities; +import com.android.dialer.enrichedcall.EnrichedCallComponent; +import com.android.dialer.enrichedcall.EnrichedCallManager; +import com.android.dialer.location.GeoUtil; import com.android.dialer.util.CallUtil; import java.util.ArrayList; import java.util.Arrays; @@ -62,6 +68,7 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { // A list of extended directories to add to the directories from the database private final List mExtendedDirectories; private final CharSequence mUnknownNameText; + private final boolean mCallAndShareEnabled; // Extended directories will have ID's that are higher than any of the id's from the database, // so that we can identify them and set them up properly. If no extended directories // exist, this will be Long.MAX_VALUE @@ -83,6 +90,9 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { int videoCapabilities = CallUtil.getVideoCallingAvailability(context); mIsVideoEnabled = (videoCapabilities & CallUtil.VIDEO_CALLING_ENABLED) != 0; mIsPresenceEnabled = (videoCapabilities & CallUtil.VIDEO_CALLING_PRESENCE) != 0; + + // TODO + mCallAndShareEnabled = true; } @Override @@ -207,7 +217,7 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { case ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY: break; // This adapter is always "phone only", so no selection needed either. default: - Log.w( + LogUtil.w( TAG, "Unsupported filter type came " + "(type: " @@ -239,6 +249,48 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { return item != null ? item.getString(PhoneQuery.LOOKUP_KEY) : null; } + public CallComposerContact getCallComposerContact(int position) { + Cursor cursor = (Cursor) getItem(position); + if (cursor == null) { + LogUtil.e("PhoneNumberListAdapter.getCallComposerContact", "cursor was null."); + return null; + } + + String displayName = cursor.getString(PhoneQuery.DISPLAY_NAME); + String number = cursor.getString(PhoneQuery.PHONE_NUMBER); + String photoUri = cursor.getString(PhoneQuery.PHOTO_URI); + Uri contactUri = + Contacts.getLookupUri( + cursor.getLong(PhoneQuery.CONTACT_ID), cursor.getString(PhoneQuery.LOOKUP_KEY)); + + CallComposerContact.Builder contact = CallComposerContact.newBuilder(); + contact + .setNumber(number) + .setPhotoId(cursor.getLong(PhoneQuery.PHOTO_ID)) + .setContactType(ContactPhotoManager.TYPE_DEFAULT) + .setNameOrNumber(displayName) + .setNumberLabel( + Phone.getTypeLabel( + mContext.getResources(), + cursor.getInt(PhoneQuery.PHONE_TYPE), + cursor.getString(PhoneQuery.PHONE_LABEL)) + .toString()); + + if (photoUri != null) { + contact.setPhotoUri(photoUri); + } + + if (contactUri != null) { + contact.setContactUri(contactUri.toString()); + } + + if (!TextUtils.isEmpty(displayName)) { + contact.setDisplayNumber(number); + } + + return contact.build(); + } + @Override protected ContactListItemView newView( Context context, int partition, Cursor cursor, int position, ViewGroup parent) { @@ -323,12 +375,13 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { final String customLabel = cursor.getString(PhoneQuery.PHONE_LABEL); // TODO cache - label = Phone.getTypeLabel(getContext().getResources(), type, customLabel); + label = Phone.getTypeLabel(mContext.getResources(), type, customLabel); } view.setLabel(label); final String text; + String number = cursor.getString(PhoneQuery.PHONE_NUMBER); if (displayNumber) { - text = cursor.getString(PhoneQuery.PHONE_NUMBER); + text = number; } else { // Display phone label. If that's null, display geocoded location for the number final String phoneLabel = cursor.getString(PhoneQuery.PHONE_LABEL); @@ -341,14 +394,32 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { } view.setPhoneNumber(text); + @CallToAction int action = ContactListItemView.NONE; + if (CompatUtils.isVideoCompatible()) { // Determine if carrier presence indicates the number supports video calling. int carrierPresence = cursor.getInt(PhoneQuery.CARRIER_PRESENCE); boolean isPresent = (carrierPresence & Phone.CARRIER_PRESENCE_VT_CAPABLE) != 0; boolean isVideoIconShown = mIsVideoEnabled && (!mIsPresenceEnabled || isPresent); - view.setShowVideoCallIcon(isVideoIconShown, mListener, position); + if (isVideoIconShown) { + action = ContactListItemView.VIDEO; + } + } + + if (isCallAndShareEnabled() && action == ContactListItemView.NONE && number != null) { + EnrichedCallManager manager = EnrichedCallComponent.get(mContext).getEnrichedCallManager(); + EnrichedCallCapabilities capabilities = manager.getCapabilities(number); + if (capabilities != null && capabilities.supportsCallComposer()) { + action = ContactListItemView.CALL_AND_SHARE; + } else if (capabilities == null + && getQueryString() != null + && getQueryString().length() >= 3) { + manager.requestCapabilities(number); + } } + + view.setCallToAction(action, mListener, position); } protected void bindSectionHeaderAndDivider(final ContactListItemView view, int position) { @@ -499,9 +570,15 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter { mListener = listener; } + public boolean isCallAndShareEnabled() { + return mCallAndShareEnabled; + } + public interface Listener { void onVideoCallIconClicked(int position); + + void onCallAndShareIconClicked(int position); } public static class PhoneQuery { diff --git a/java/com/android/contacts/common/list/PhoneNumberPickerFragment.java b/java/com/android/contacts/common/list/PhoneNumberPickerFragment.java index 4ae81529bc99b06900d10381e87b1d008251420a..8f25f82a579e0060cc133c196ea8aaae59d25fc9 100644 --- a/java/com/android/contacts/common/list/PhoneNumberPickerFragment.java +++ b/java/com/android/contacts/common/list/PhoneNumberPickerFragment.java @@ -15,6 +15,8 @@ */ package com.android.contacts.common.list; +import android.content.ComponentName; +import android.content.Intent; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; @@ -28,17 +30,23 @@ import android.view.View; import android.view.ViewGroup; import com.android.contacts.common.R; import com.android.contacts.common.util.AccountFilterUtil; -import com.android.dialer.callintent.nano.CallSpecificAppData; +import com.android.dialer.callcomposer.CallComposerContact; +import com.android.dialer.callintent.CallInitiationType; +import com.android.dialer.callintent.CallInitiationType.Type; +import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; +import com.android.dialer.enrichedcall.EnrichedCallComponent; +import com.android.dialer.enrichedcall.EnrichedCallManager; import com.android.dialer.logging.Logger; +import com.android.dialer.protos.ProtoParsers; import java.util.Set; import org.json.JSONException; import org.json.JSONObject; /** Fragment containing a phone number list for picking. */ public class PhoneNumberPickerFragment extends ContactEntryListFragment - implements PhoneNumberListAdapter.Listener { + implements PhoneNumberListAdapter.Listener, EnrichedCallManager.CapabilitiesListener { private static final String KEY_FILTER = "filter"; private OnPhoneNumberPickerActionListener mListener; @@ -56,8 +64,7 @@ public class PhoneNumberPickerFragment extends ContactEntryListFragment mLoadFinishedListeners = - new ArraySet(); + private final Set mLoadFinishedListeners = new ArraySet<>(); private CursorReranker mCursorReranker; @@ -81,6 +88,18 @@ public class PhoneNumberPickerFragment extends ContactEntryListFragment { @Override public Contact loadInBackground() { - Log.e(TAG, "loadInBackground=" + mLookupUri); + LogUtil.e(TAG, "loadInBackground=" + mLookupUri); try { final ContentResolver resolver = getContext().getContentResolver(); final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(resolver, mLookupUri); @@ -264,7 +264,7 @@ public class ContactLoader extends AsyncTaskLoader { } return result; } catch (Exception e) { - Log.e(TAG, "Error loading the contact: " + mLookupUri, e); + LogUtil.e(TAG, "Error loading the contact: " + mLookupUri, e); return Contact.forError(mRequestedUri, e); } } @@ -274,7 +274,7 @@ public class ContactLoader extends AsyncTaskLoader { Cursor cursor = resolver.query(entityUri, ContactQuery.COLUMNS, null, null, Contacts.Entity.RAW_CONTACT_ID); if (cursor == null) { - Log.e(TAG, "No cursor returned in loadContactEntity"); + LogUtil.e(TAG, "No cursor returned in loadContactEntity"); return Contact.forNotFound(mRequestedUri); } @@ -521,10 +521,7 @@ public class ContactLoader extends AsyncTaskLoader { cursorColumnToContentValues(cursor, cv, ContactQuery.CHAT_CAPABILITY); cursorColumnToContentValues(cursor, cv, ContactQuery.TIMES_USED); cursorColumnToContentValues(cursor, cv, ContactQuery.LAST_TIME_USED); - if (CompatUtils.isMarshmallowCompatible()) { - cursorColumnToContentValues(cursor, cv, ContactQuery.CARRIER_PRESENCE); - } - + cursorColumnToContentValues(cursor, cv, ContactQuery.CARRIER_PRESENCE); return cv; } @@ -577,7 +574,7 @@ public class ContactLoader extends AsyncTaskLoader { Resources resources = pm.getResourcesForApplication(packageName); directoryType = resources.getString(typeResourceId); } catch (NameNotFoundException e) { - Log.w( + LogUtil.w( TAG, "Contact directory resource not found: " + packageName + "." + typeResourceId); } } @@ -692,11 +689,15 @@ public class ContactLoader extends AsyncTaskLoader { mLookupUri = result.getLookupUri(); if (!result.isDirectoryEntry()) { - Log.i(TAG, "Registering content observer for " + mLookupUri); if (mObserver == null) { mObserver = new ForceLoadContentObserver(); } - getContext().getContentResolver().registerContentObserver(mLookupUri, true, mObserver); + + if (PermissionsUtil.hasContactsReadPermissions(getContext())) { + getContext().getContentResolver().registerContentObserver(mLookupUri, true, mObserver); + } else { + LogUtil.w("ContactLoader.deliverResult", "contacts permission not available"); + } } if (mPostViewNotification) { @@ -732,7 +733,7 @@ public class ContactLoader extends AsyncTaskLoader { try { context.startService(intent); } catch (Exception e) { - Log.e(TAG, "Error sending message to source-app", e); + LogUtil.e(TAG, "Error sending message to source-app", e); } } } @@ -919,9 +920,7 @@ public class ContactLoader extends AsyncTaskLoader { static { List projectionList = Lists.newArrayList(COLUMNS_INTERNAL); - if (CompatUtils.isMarshmallowCompatible()) { - projectionList.add(Data.CARRIER_PRESENCE); - } + projectionList.add(Data.CARRIER_PRESENCE); COLUMNS = projectionList.toArray(new String[projectionList.size()]); } } diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_ab_search.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_ab_search.png new file mode 100644 index 0000000000000000000000000000000000000000..d86b2195afb90f0a4fbc29808538530ad76b764d Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_ab_search.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_arrow_back_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_arrow_back_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..ddbb2c459647e3b93d068e37de24f02c4b6dc3e3 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_arrow_back_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_business_white_120dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_business_white_120dp.png new file mode 100644 index 0000000000000000000000000000000000000000..d5942dcad2de787175d0dd426ed91096e2b77e28 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_business_white_120dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_call_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_call_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..4dc5065155baeba719d76845d4398431c289cde0 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_call_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_call_note_white_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_call_note_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..503e58e22f7d39fcba9a7793d8e6d285233e8f10 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_call_note_white_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_close_dk.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_close_dk.png new file mode 100644 index 0000000000000000000000000000000000000000..9695529351a0e736fc7b469572eaffff0bff0f89 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_close_dk.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_create_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_create_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..540ab4deeaf68d799ce6b01a2b7679a7c78b1e8b Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_create_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_group_white_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_group_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..017e4bbf71ec8e30561efa3b7f84a4bc1523b075 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_group_white_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_history_white_drawable_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_history_white_drawable_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..703d30b92583a3fc339d8a4bf341f0853410eb86 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_history_white_drawable_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_info_outline_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_info_outline_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..c7b1113cfef22bcec86ead7ae67be12326276cab Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_info_outline_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_back.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_back.png new file mode 100644 index 0000000000000000000000000000000000000000..deb3a6dc1db49106b72e5fe195d2dd41f6c243a6 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_back.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_group_dk.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_group_dk.png new file mode 100644 index 0000000000000000000000000000000000000000..06bd18fbb32cb70607f68fd2ec8318e54e9da1f7 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_group_dk.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_group_lt.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_group_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..d829d11e20aa80a6ef27e56b5956502d89b0240d Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_group_lt.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_overflow_lt.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_overflow_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba12950c81dd66dc20f2b1877211c8c4019e222 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_overflow_lt.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_person_dk.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_person_dk.png new file mode 100644 index 0000000000000000000000000000000000000000..5ff3ac57484a0e11d87f932faf68900feaad7315 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_person_dk.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_person_lt.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_person_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..b4ebfc7b2ebb9363ccdd308ada2ba4045a632e47 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_person_lt.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_remove_field_holo_light.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_remove_field_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..03fd2fb108bc599a117eb739751d9157ceb432c0 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_remove_field_holo_light.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_dk.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_dk.png new file mode 100644 index 0000000000000000000000000000000000000000..e8cb0f5fec5b5599df3d1c9a4fb1f513066bedac Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_dk.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_holo_light.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..45137967c532567a1e553b89f90b951c8b63390d Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_holo_light.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_lt.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..1c9bb81fa728fb670f55c5b7c34d647d3ec8a948 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_menu_star_lt.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_person_24dp.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_person_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..56708b0bad6c193edb0bb0c7f39897566aff4b20 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_person_24dp.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_phone_attach.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_phone_attach.png new file mode 100644 index 0000000000000000000000000000000000000000..84b1227bde69e11b4a01ddc9f603ff2b68bf4fb3 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_phone_attach.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_rx_videocam.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_rx_videocam.png new file mode 100644 index 0000000000000000000000000000000000000000..ccdda670172b4521f169c01e47b47535d61613bc Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_rx_videocam.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_scroll_handle.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_scroll_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa29b8520b8a6a6d3a1cdff0037327e2ce0d02e Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_scroll_handle.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_tx_videocam.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_tx_videocam.png new file mode 100644 index 0000000000000000000000000000000000000000..603ddc8950b3d6ce62d05b586fe1672fdc182f6b Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_tx_videocam.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_videocam.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_videocam.png new file mode 100644 index 0000000000000000000000000000000000000000..97905c9f59f2e9e1a39596965bd1840d52c4a424 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_videocam.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/ic_voicemail_avatar.png b/java/com/android/contacts/common/res/drawable-hdpi/ic_voicemail_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..2121878ae9db8a3aaa4f0872780ee49f474c992b Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/ic_voicemail_avatar.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_activated_holo.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_activated_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea7afa00e2bfe057472ed5a196080fc80ad7383 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_activated_holo.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_background_holo.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_background_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..cddf9be75cb961b8eb07c840f03b94cf9d75c4f0 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_background_holo.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_focused_holo.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_focused_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..86578be45ae3fbbd3a3c0be96fd487cdca7f95b1 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_focused_holo.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_longpressed_holo_light.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_longpressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..e9afcc9248a49f4cfd95a0cb07504add2789043a Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_longpressed_holo_light.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_pressed_holo_light.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..2054530ed2870bfa7dbc60a2d142ba3776e63d33 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_pressed_holo_light.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_section_divider_holo_custom.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_section_divider_holo_custom.9.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f17568e27a95f5854a49244dbbbb5f3b616490 Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_section_divider_holo_custom.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-hdpi/list_title_holo.9.png b/java/com/android/contacts/common/res/drawable-hdpi/list_title_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..ae937176e07806c0253f2ad1b2a98af020c7048f Binary files /dev/null and b/java/com/android/contacts/common/res/drawable-hdpi/list_title_holo.9.png differ diff --git a/java/com/android/contacts/common/res/drawable-mdpi/ic_business_white_120dp.png b/java/com/android/contacts/common/res/drawable-mdpi/ic_business_white_120dp.png deleted file mode 100644 index 3dddca51635a99190254ac188cead7290fac43d0..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-mdpi/ic_business_white_120dp.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-mdpi/ic_voicemail_avatar.png b/java/com/android/contacts/common/res/drawable-mdpi/ic_voicemail_avatar.png deleted file mode 100644 index a7875c5def6b25301cc9bc3b5b75d441e4c66c55..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-mdpi/ic_voicemail_avatar.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-xhdpi/ic_business_white_120dp.png b/java/com/android/contacts/common/res/drawable-xhdpi/ic_business_white_120dp.png deleted file mode 100644 index 6256300b420e27596c39ee1b073723d76d0d8e1f..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-xhdpi/ic_business_white_120dp.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-xhdpi/ic_voicemail_avatar.png b/java/com/android/contacts/common/res/drawable-xhdpi/ic_voicemail_avatar.png deleted file mode 100644 index 8dc1d595bde9d72b77a6132ce3435a7284d30354..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-xhdpi/ic_voicemail_avatar.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-xxhdpi/ic_business_white_120dp.png b/java/com/android/contacts/common/res/drawable-xxhdpi/ic_business_white_120dp.png deleted file mode 100644 index 8d67e448fc015039913e7e5bc48abf49be2b4744..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-xxhdpi/ic_business_white_120dp.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-xxhdpi/ic_voicemail_avatar.png b/java/com/android/contacts/common/res/drawable-xxhdpi/ic_voicemail_avatar.png deleted file mode 100644 index 5d22cbeea802061601f5f59ce4645303b06ca35d..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-xxhdpi/ic_voicemail_avatar.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-xxxhdpi/ic_business_white_120dp.png b/java/com/android/contacts/common/res/drawable-xxxhdpi/ic_business_white_120dp.png deleted file mode 100644 index 1741675def6be036e0d491e2d385bb9a950c65e8..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-xxxhdpi/ic_business_white_120dp.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable-xxxhdpi/ic_voicemail_avatar.png b/java/com/android/contacts/common/res/drawable-xxxhdpi/ic_voicemail_avatar.png deleted file mode 100644 index 762b6364830f29778f44dd9fcdb050cbe82c8ec2..0000000000000000000000000000000000000000 Binary files a/java/com/android/contacts/common/res/drawable-xxxhdpi/ic_voicemail_avatar.png and /dev/null differ diff --git a/java/com/android/contacts/common/res/drawable/ic_call_and_share.xml b/java/com/android/contacts/common/res/drawable/ic_call_and_share.xml new file mode 100644 index 0000000000000000000000000000000000000000..be0cdd3585353f27f2fc9275904212f63f34e746 --- /dev/null +++ b/java/com/android/contacts/common/res/drawable/ic_call_and_share.xml @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/java/com/android/contacts/common/res/drawable/ic_search_video_call.xml b/java/com/android/contacts/common/res/drawable/ic_search_video_call.xml index 68c46fed608f8f6af895fdc46bb53f50b830612c..0fe0367e1996672dc960be2f278453bb44d70c47 100644 --- a/java/com/android/contacts/common/res/drawable/ic_search_video_call.xml +++ b/java/com/android/contacts/common/res/drawable/ic_search_video_call.xml @@ -18,4 +18,5 @@ + android:tint="@color/search_video_call_icon_tint" + android:background="?attr/selectableItemBackgroundBorderless"/> diff --git a/java/com/android/contacts/common/res/mipmap-hdpi/ic_contacts_launcher.png b/java/com/android/contacts/common/res/mipmap-hdpi/ic_contacts_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..64eff002fb71043b01f5b14aa9563d34fb4cc693 Binary files /dev/null and b/java/com/android/contacts/common/res/mipmap-hdpi/ic_contacts_launcher.png differ diff --git a/java/com/android/contacts/common/res/values-af/strings.xml b/java/com/android/contacts/common/res/values-af/strings.xml index 1f1b33c6243b2465c60dc8c799bbee3c25d76a9a..9b8bf7886023e20fcef668d3458a6a4114c75cf0 100644 --- a/java/com/android/contacts/common/res/values-af/strings.xml +++ b/java/com/android/contacts/common/res/values-af/strings.xml @@ -261,5 +261,8 @@ "Diensbepalings" "Oopbronlisensies" "Kon nie die URL oopmaak nie." - "Maak video-oproep" + + + + diff --git a/java/com/android/contacts/common/res/values-am/strings.xml b/java/com/android/contacts/common/res/values-am/strings.xml index 81b87fc6168baf2dd690243890fe578525c07a1e..1e56dd26bbcfa6a6e09496db6b6d07d63eea6c05 100644 --- a/java/com/android/contacts/common/res/values-am/strings.xml +++ b/java/com/android/contacts/common/res/values-am/strings.xml @@ -261,5 +261,8 @@ "የአገልግሎት ውል" "የክፍት ምንጭ ፈቃዶች" "ዩ አር ኤሉን ለመክፈት አልተሳካም።" - "የቪዲዮ ጥሪ አስቀምጥ" + + + + diff --git a/java/com/android/contacts/common/res/values-ar/strings.xml b/java/com/android/contacts/common/res/values-ar/strings.xml index b878582a112f857e08b55095b691c41abb0d5a60..366613d85d74aaa2f366a8db17936d2db9a81c9b 100644 --- a/java/com/android/contacts/common/res/values-ar/strings.xml +++ b/java/com/android/contacts/common/res/values-ar/strings.xml @@ -269,5 +269,8 @@ "بنود الخدمة" "تراخيص البرامج مفتوحة المصدر" "‏فشل فتح عنوان URL." - "إجراء مكالمة فيديو" + + + + diff --git a/java/com/android/contacts/common/res/values-az/strings.xml b/java/com/android/contacts/common/res/values-az/strings.xml index da6f0a94057d8e33df750e6bb0e3598f81e8fe8e..04647a5806433e35d23f7fae4eca0efcf034c7be 100644 --- a/java/com/android/contacts/common/res/values-az/strings.xml +++ b/java/com/android/contacts/common/res/values-az/strings.xml @@ -261,5 +261,8 @@ "Xidmət şərtləri" "Açıq mənbə lisenziyaları" "Linki açmaq alınmadı." - "Video zəng edin" + + + + diff --git a/java/com/android/contacts/common/res/values-b+sr+Latn/strings.xml b/java/com/android/contacts/common/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..4ef8bebc3acbb4e3099e0510dbb5b6ca264b3d2b --- /dev/null +++ b/java/com/android/contacts/common/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,270 @@ + + + + + "Tekst je kopiran" + "Kopiraj u priv. memoriju" + "Pozovi %s" + "Pozovi kućni telefon" + "Pozovi mobilni telefon" + "Pozovi poslovni telefon" + "Pozovi poslovni faks" + "Pozovi kućni faks" + "Pozovi pejdžer" + "Pozovi" + "Pozovi za povratni poziv" + "Pozovi telefon u automobilu" + "Pozovi glavni telefon preduzeća" + "Pozovi ISDN" + "Pozovi glavni telefon" + "Pozovi faks" + "Pozovi radio" + "Pozovi teleks" + "Pozovi TTY/TDD" + "Pozovi poslovni mobilni telefon" + "Pozovi poslovni pejdžer" + "Pozovi %s" + "Pozovi broj za MMS" + "%s (pozovi)" + "Pošalji SMS na %s" + "Pošalji SMS na kućni telefon" + "Pošalji SMS na mobilni telefon" + "Pošalji SMS na poslovni telefon" + "Pošalji SMS na poslovni faks" + "Pošalji SMS na kućni faks" + "Pošalji SMS na pejdžer" + "Pošalji SMS" + "Pošalji SMS za povratni poziv" + "Pošalji SMS na telefon u automobilu" + "Pošalji SMS na glavni broj telefona preduzeća" + "Pošalji SMS na ISDN" + "Pošalji SMS na glavni telefon" + "Pošalji SMS na faks" + "Pošalji SMS na radio" + "Pošalji SMS na teleks" + "Pošalji SMS na TTY/TDD" + "Pošalji SMS na poslovni mobilni telefon" + "Pošalji SMS na poslovni pejdžer" + "Pošalji SMS na %s" + "Pošalji SMS na broj za MMS" + "%s (pošalji SMS)" + "Brišete često kontaktirane?" + "Obrisaćete listu često kontaktiranih u aplikacijama Kontakti i Telefon, pa će imejl aplikacije morati ponovo da prikupe informacije o adresiranju." + "Brisanje često kontaktiranih..." + "Dostupan/na" + "Odsutan/na" + "Zauzet/a" + "Kontakti" + "Drugo" + "Direktorijum" + "Direktorijum za Work" + "Svi kontakti" + "Ja" + "Pretražuje se…" + "Pronađeno je više od %d." + "Nema kontakata" + + Pronađen je %d + Pronađena su %d + Pronađeno je %d + + "Brzi kontakt za korisnika %1$s" + "(Nema imena)" + "Često pozivani" + "Često kontaktirani" + "Prikaži kontakt" + "Svi kontakti sa brojevima telefona" + "Kontakti sa profila za Work" + "Prikaži ažuriranja" + "Samo na uređaju, ne sinhronizuje se" + "Ime" + "Nadimak" + "Ime" + "Imenu" + "Prezimenu" + "Prefiks za ime" + "Srednje ime" + "Sufiks imena" + "Ime – fonetski" + "Ime – fonetski" + "Srednje ime – fonetski" + "Prezime – fonetski" + "Telefon" + "Pošalji imejl" + "Adresa" + "Razmena trenutnih poruka" + "Organizacija" + "Odnos" + "Poseban dan" + "SMS" + "Adresa" + "Preduzeće" + "Naziv" + "Beleške" + "SIP" + "Veb-sajt" + "Grupe" + "Pošalji imejl na kućnu imejl adresu" + "Pošalji imejl na mobilni telefon" + "Pošalji imejl na poslovnu imejl adresu" + "Pošalji imejl" + "Pošalji imejl na %s" + "Pošalji imejl" + "Ulica" + "Poštanski fah" + "Kraj" + "Grad" + "Država" + "Poštanski broj" + "Zemlja" + "Prikaži kućnu adresu" + "Prikaži poslovnu adresu" + "Prikaži adresu" + "Prikaži adresu %s" + "Započni ćaskanje preko AIM-a" + "Započni ćaskanje preko Windows Live-a" + "Započni ćaskanje preko Yahoo-a" + "Započni ćaskanje preko Skype-a" + "Započni ćaskanje preko QQ-a" + "Započni ćaskanje preko Google Talk-a" + "Započni ćaskanje preko ICQ-a" + "Započni ćaskanje preko Jabber-a" + "Ćaskanje" + "izbriši" + "Proširivanje ili skupljanje polja za nazive" + "Proširi ili skupi polja za fonetsko ime" + "Svi kontakti" + "Gotovo" + "Otkaži" + "Kontakti u grupi %s" + "Kontakti u prilagođenom prikazu" + "Pojedinačni kontakt" + "Sačuvajte uvezene kontakte na:" + "Uvezi sa SIM kartice" + "Uvoz sa SIM kartice ^1^2" + "Uvoz sa SIM kartice %1$s" + "Uvezi iz .vcf datoteke" + "Želite li da otkažete uvoz datoteke %s?" + "Želite li da otkažete izvoz datoteke %s?" + "Nije moguće otkazati vCard uvoz/izvoz" + "Nepoznata greška." + "Nismo uspeli da otvorimo datoteku „%s“: %s." + "Nije moguće pokrenuti program za izvoz: „%s“" + "Nema kontakata za izvoz." + "Onemogućili ste obaveznu dozvolu." + "Došlo je do greške pri izvozu: „%s“" + "Zahtevani naziv datoteke je predugačak („%s“)." + "U/I greška" + "Nema dovoljno memorije. Datoteka je možda prevelika." + "Iz neočekivanog razloga nije moguće raščlaniti vCard datoteku." + "Format nije podržan." + "Nije moguće prikupiti metapodatke navedenih vCard datoteka." + "Nije moguć uvoz jedne ili više datoteka (%s)." + "Izvoz datoteke %s je završen." + "Izvoz kontakata je završen." + "Izvoz kontakata je završen. Kliknite na obaveštenje da biste ih delili." + "Dodirnite da biste delili kontakte." + "Izvoz datoteke %s je otkazan." + "Izvoz podataka o kontaktima je u toku" + "Podaci o kontaktima se izvoze." + "Preuzimanje informacija iz baze podataka nije moguće." + "Nema kontakata za izvoz. Ako imate kontakte na uređaju, neki dobavljači podataka možda ne dozvoljavaju izvoz kontakata sa uređaja." + "Program za izradu vCard datoteka se nije ispravno pokrenuo." + "Izvoz nije moguć" + "Podaci o kontaktima nizu izvezeni.\nRazlog: „%s“" + "Uvoz kontakta %s" + "Čitanje vCard podataka nije moguće" + "Čitanje vCard podataka je otkazano" + "Uvoz vCard datoteke %s je završen" + "Uvoz datoteke %s je otkazan" + "Datoteka %s će uskoro biti uvezena." + "Datoteka će uskoro biti uvezena." + "Zahtev za uvoz vCard datoteke je odbijen. Probajte ponovo kasnije." + "Datoteka %s će uskoro biti izvezena." + "Datoteka će uskoro biti izvezena." + "Kontakti će uskoro biti izvezeni." + "Zahtev za izvoz vCard datoteke je odbijen. Probajte ponovo kasnije." + "kontakt" + "Keširanje vCard datoteka u lokalnu privremenu memoriju. Uvoz će uskoro započeti." + "Uvoz vCard datoteke nije moguć." + "Kontakt preko NFC-a" + "Želite li da izvezete kontakte?" + "Keširanje" + "Uvozimo %s/%s: %s" + "Izvezi u .vcf datoteku" + "Sortiraj prema" + "Imenu" + "Prezimenu" + "Format imena i prezimena" + "Prvo ime" + "Prvo prezime" + "Podrazumevani nalog za nove kontakte" + "Sinhronizujte metapodatke kontakata" + "O Kontaktima" + "Podešavanja" + "Deli vidljive kontakte" + "Nije uspelo deljenje vidljivih kontakata." + "Deli omiljene kontakte" + "Deli sve kontakte" + "Deljenje kontakata nije uspelo." + "Uvoz/izvoz kontakata" + "Uvezi kontakte" + "Ovaj kontakt ne može da se deli." + "Nema kontakata za deljenje." + "Pretraži" + "Pronađite kontakte" + "Omiljeno" + "Nema kontakata." + "Nema vidljivih kontakata." + "Nema omiljenih" + "Nema kontakata u grupi %s" + "Obriši često kontaktirane" + "Izaberite SIM karticu" + "Upravljaj nalozima" + "Uvezi/izvezi" + "preko %1$s" + "%1$s preko %2$s" + "zaustavljanje pretraživanja" + "Brisanje pretrage" + "Opcije prikazivanja kontakata" + "Nalog" + "Uvek koristi ovo za pozive" + "Pozovi pomoću" + "Poziv sa beleškom" + "Unesite belešku koju ćete poslati uz poziv..." + "POŠALJI I POZOVI" + "%1$s/%2$s" + "%1$s%2$s" + "Kartica %1$s." + + Kartica %1$s. %2$d nepročitana stavka. + Kartica %1$s. %2$d nepročitane stavke. + Kartica %1$s. %2$d nepročitanih stavki. + + "Verzija" + "Licence otvorenog koda" + "Detalji licence za softver otvorenog koda" + "Politika privatnosti" + "Uslovi korišćenja usluge" + "Licence otvorenog koda" + "Otvaranje URL-a nije uspelo." + + + + + diff --git a/java/com/android/contacts/common/res/values-be/strings.xml b/java/com/android/contacts/common/res/values-be/strings.xml index d4f8e4cf2a8c9d66d729f82758e175acfe21c3c1..95be6522106322543dfdcc626b863989dacc942c 100644 --- a/java/com/android/contacts/common/res/values-be/strings.xml +++ b/java/com/android/contacts/common/res/values-be/strings.xml @@ -265,5 +265,8 @@ "Умовы абслугоўвання" "Ліцэнзіі ПЗ з адкрытым зыходным кодам" "Не ўдалося адкрыць URL." - "Зрабіць відэавыклік" + + + + diff --git a/java/com/android/contacts/common/res/values-bg/strings.xml b/java/com/android/contacts/common/res/values-bg/strings.xml index 23345d8eaee4584f7580270f5c917818f87234dc..68a9d1215e8c881183114eb90da818a776271058 100644 --- a/java/com/android/contacts/common/res/values-bg/strings.xml +++ b/java/com/android/contacts/common/res/values-bg/strings.xml @@ -261,5 +261,8 @@ "Общи условия" "Лицензи за отворен код" "Отварянето на URL адреса не бе успешно." - "Извършване на видеообаждане" + + + + diff --git a/java/com/android/contacts/common/res/values-bn/strings.xml b/java/com/android/contacts/common/res/values-bn/strings.xml index d7df63aa198a7c66002636765b3e93acab10633b..0c10cc8285a8a6bf7959b97a35816bfc16407c2e 100644 --- a/java/com/android/contacts/common/res/values-bn/strings.xml +++ b/java/com/android/contacts/common/res/values-bn/strings.xml @@ -261,5 +261,8 @@ "পরিষেবার শর্তাবলী" "মুক্ত উৎস লাইসেন্সগুলি" "url খুলতে ব্যর্থ হয়েছে৷" - "ভিডিও কল করুন" + + + + diff --git a/java/com/android/contacts/common/res/values-bs/strings.xml b/java/com/android/contacts/common/res/values-bs/strings.xml index d8916d7d58d74ef3201c1fabd00c18f220cdeb18..b008069272208a464a7e7ab8f875d697435ba129 100644 --- a/java/com/android/contacts/common/res/values-bs/strings.xml +++ b/java/com/android/contacts/common/res/values-bs/strings.xml @@ -263,5 +263,8 @@ "Uslovi pružanja usluge" "Licence otvorenog koda" "Otvaranje URL-a nije uspjelo." - "Uputi videopoziv" + + + + diff --git a/java/com/android/contacts/common/res/values-ca/strings.xml b/java/com/android/contacts/common/res/values-ca/strings.xml index c08c13e7a30eb06df8eb4b52b765fca52b095d23..0e4b2c5ee32edef7f60bd5eff5576bc16ceebf64 100644 --- a/java/com/android/contacts/common/res/values-ca/strings.xml +++ b/java/com/android/contacts/common/res/values-ca/strings.xml @@ -261,5 +261,8 @@ "Condicions del servei" "Llicències de programari lliure" "No s\'ha pogut obrir l\'URL." - "Fa una videotrucada" + + + + diff --git a/java/com/android/contacts/common/res/values-cs/strings.xml b/java/com/android/contacts/common/res/values-cs/strings.xml index 743a12ce9cc1dec9909679009930b2a584b20cdf..0e9646fe2b99bc53384bf5fc5bea92a2478a4c84 100644 --- a/java/com/android/contacts/common/res/values-cs/strings.xml +++ b/java/com/android/contacts/common/res/values-cs/strings.xml @@ -265,5 +265,8 @@ "Smluvní podmínky" "Licence open source" "Adresu URL se nepodařilo otevřít." - "Zahájit videohovor" + + + + diff --git a/java/com/android/contacts/common/res/values-da/strings.xml b/java/com/android/contacts/common/res/values-da/strings.xml index 8bfa56d935ea0db5ab603498a5e974d5abbccef4..534225ece20bd15f7b37e3b63444513c924685b3 100644 --- a/java/com/android/contacts/common/res/values-da/strings.xml +++ b/java/com/android/contacts/common/res/values-da/strings.xml @@ -261,5 +261,8 @@ "Servicevilkår" "Open source-licenser" "Webadressen kunne ikke åbnes." - "Foretag videoopkald" + + + + diff --git a/java/com/android/contacts/common/res/values-de/strings.xml b/java/com/android/contacts/common/res/values-de/strings.xml index 146fa966e1434915c6b23a84f4ebab82a9fddf0e..ffc5de0e91c5e13974804901646cd59567878047 100644 --- a/java/com/android/contacts/common/res/values-de/strings.xml +++ b/java/com/android/contacts/common/res/values-de/strings.xml @@ -261,5 +261,8 @@ "Nutzungsbedingungen" "Open-Source-Lizenzen" "Die URL konnte nicht geöffnet werden." - "Videoanruf starten" + + + + diff --git a/java/com/android/contacts/common/res/values-el/strings.xml b/java/com/android/contacts/common/res/values-el/strings.xml index 510fcb0464293a25dd40ee359db5b574519d159a..5b1c7da2b9c5229d463777e32a3ff67068a8e7d9 100644 --- a/java/com/android/contacts/common/res/values-el/strings.xml +++ b/java/com/android/contacts/common/res/values-el/strings.xml @@ -261,5 +261,8 @@ "Όροι Παροχής Υπηρεσιών" "Άδειες λογισμικού ανοικτού κώδικα" "Αποτυχία ανοίγματος url." - "Πραγματοποίηση βιντεοκλήσης" + + + + diff --git a/java/com/android/contacts/common/res/values-en-rAU/strings.xml b/java/com/android/contacts/common/res/values-en-rAU/strings.xml index 79a09fff0d8b4424593d5ec3f113c8ccc2cfaed8..1040b1d4e842b59a11ba93e912a99f08d8bb98e1 100644 --- a/java/com/android/contacts/common/res/values-en-rAU/strings.xml +++ b/java/com/android/contacts/common/res/values-en-rAU/strings.xml @@ -261,5 +261,8 @@ "Terms of Service" "Open-source licences" "Failed to open the URL." - "Place video call" + + + + diff --git a/java/com/android/contacts/common/res/values-en-rGB/strings.xml b/java/com/android/contacts/common/res/values-en-rGB/strings.xml index 79a09fff0d8b4424593d5ec3f113c8ccc2cfaed8..1040b1d4e842b59a11ba93e912a99f08d8bb98e1 100644 --- a/java/com/android/contacts/common/res/values-en-rGB/strings.xml +++ b/java/com/android/contacts/common/res/values-en-rGB/strings.xml @@ -261,5 +261,8 @@ "Terms of Service" "Open-source licences" "Failed to open the URL." - "Place video call" + + + + diff --git a/java/com/android/contacts/common/res/values-en-rIN/strings.xml b/java/com/android/contacts/common/res/values-en-rIN/strings.xml index 79a09fff0d8b4424593d5ec3f113c8ccc2cfaed8..1040b1d4e842b59a11ba93e912a99f08d8bb98e1 100644 --- a/java/com/android/contacts/common/res/values-en-rIN/strings.xml +++ b/java/com/android/contacts/common/res/values-en-rIN/strings.xml @@ -261,5 +261,8 @@ "Terms of Service" "Open-source licences" "Failed to open the URL." - "Place video call" + + + + diff --git a/java/com/android/contacts/common/res/values-es-rUS/strings.xml b/java/com/android/contacts/common/res/values-es-rUS/strings.xml index f44426bebdfc98f6415d3a517dbdac2148c8769a..59ac2ce8b68a90e0a1452fe0e759742a09b292e3 100644 --- a/java/com/android/contacts/common/res/values-es-rUS/strings.xml +++ b/java/com/android/contacts/common/res/values-es-rUS/strings.xml @@ -261,5 +261,8 @@ "Condiciones del servicio" "Licencias de código abierto" "No se pudo abrir la url." - "Hacer una videollamada" + + + + diff --git a/java/com/android/contacts/common/res/values-es/strings.xml b/java/com/android/contacts/common/res/values-es/strings.xml index 39ab71487553ac495c12955975c02b23c662ef52..3307e6a78d6808efee39ccff406dee8ef2b905be 100644 --- a/java/com/android/contacts/common/res/values-es/strings.xml +++ b/java/com/android/contacts/common/res/values-es/strings.xml @@ -261,5 +261,8 @@ "Condiciones de Servicio" "Licencias de código abierto" "No se ha podido abrir la URL." - "Hacer videollamada" + + + + diff --git a/java/com/android/contacts/common/res/values-et/strings.xml b/java/com/android/contacts/common/res/values-et/strings.xml index 5e9d5c729ab77cbdf19cee39d5d0b9d59f7001e3..82d44b254d3175cee8eda31f4fad775822b890e4 100644 --- a/java/com/android/contacts/common/res/values-et/strings.xml +++ b/java/com/android/contacts/common/res/values-et/strings.xml @@ -261,5 +261,8 @@ "Teenusetingimused" "Avatud lähtekoodi litsentsid" "URL-i avamine ebaõnnestus." - "Videokõne tegemine" + + + + diff --git a/java/com/android/contacts/common/res/values-eu/strings.xml b/java/com/android/contacts/common/res/values-eu/strings.xml index 84c933094106a9e8f8484fa535e094981d54c68b..1a101c92e54d95cdd825ac534f5051bec734b330 100644 --- a/java/com/android/contacts/common/res/values-eu/strings.xml +++ b/java/com/android/contacts/common/res/values-eu/strings.xml @@ -261,5 +261,8 @@ "Zerbitzu-baldintzak" "Kode irekiko lizentziak" "Ezin izan da ireki URLa." - "Egin bideo-deia" + + + + diff --git a/java/com/android/contacts/common/res/values-fa/strings.xml b/java/com/android/contacts/common/res/values-fa/strings.xml index e583a765d0a39f23996bf507e5c7b18239caefa7..dde50c136819a75f4f197c60323f5ddb0662f7d7 100644 --- a/java/com/android/contacts/common/res/values-fa/strings.xml +++ b/java/com/android/contacts/common/res/values-fa/strings.xml @@ -261,5 +261,8 @@ "شرایط خدمات" "مجوزهای منبع آزاد" "نشانی وب باز نشد." - "برقراری تماس ویدئویی" + + + + diff --git a/java/com/android/contacts/common/res/values-fi/strings.xml b/java/com/android/contacts/common/res/values-fi/strings.xml index 01468c354436cfe18e1812f3d25cfda3b39cfa1b..370827a15248fe2dd65a37a3de2c258af3d3bbdf 100644 --- a/java/com/android/contacts/common/res/values-fi/strings.xml +++ b/java/com/android/contacts/common/res/values-fi/strings.xml @@ -261,5 +261,8 @@ "Käyttöehdot" "Avoimen lähdekoodin käyttöluvat" "URL-osoitteen avaus epäonnistui." - "Soita videopuhelu" + + + + diff --git a/java/com/android/contacts/common/res/values-fr-rCA/strings.xml b/java/com/android/contacts/common/res/values-fr-rCA/strings.xml index cdeb4f0979c5e8fe86cd5443bca436f81501b919..d392e0c9bcba6241e5e33a0b4d7f8efe63f0720f 100644 --- a/java/com/android/contacts/common/res/values-fr-rCA/strings.xml +++ b/java/com/android/contacts/common/res/values-fr-rCA/strings.xml @@ -261,5 +261,8 @@ "Modalités" "Licences de logiciels libres" "Échec de l\'ouverture de l\'URL." - "Faire un appel vidéo" + + + + diff --git a/java/com/android/contacts/common/res/values-fr/strings.xml b/java/com/android/contacts/common/res/values-fr/strings.xml index c0b20db1f8fa52d3ac139aa7a59d4da0ef4cc3dd..504f40b8af7e242a8a4bc09d2518b7f9db5c5f6e 100644 --- a/java/com/android/contacts/common/res/values-fr/strings.xml +++ b/java/com/android/contacts/common/res/values-fr/strings.xml @@ -261,5 +261,8 @@ "Conditions d\'utilisation" "Licences Open Source" "Impossible d\'ouvrir l\'URL." - "Passer un appel vidéo" + + + + diff --git a/java/com/android/contacts/common/res/values-gl/strings.xml b/java/com/android/contacts/common/res/values-gl/strings.xml index 672f82baf72d336158dcdeba701cfa63455020c3..e1e2c11d6f42a901e7ef40ba632fbe935a437270 100644 --- a/java/com/android/contacts/common/res/values-gl/strings.xml +++ b/java/com/android/contacts/common/res/values-gl/strings.xml @@ -261,5 +261,8 @@ "Condicións de servizo" "Licenzas de código aberto" "Produciuse un erro ao abrir o URL." - "Facer videochamada" + + + + diff --git a/java/com/android/contacts/common/res/values-gu/strings.xml b/java/com/android/contacts/common/res/values-gu/strings.xml index 787e1d93a1e5fae1174dd9764ad533a559b42c3a..19dbb8caf0c60188abaf0efd0abc65ccb7b13b7b 100644 --- a/java/com/android/contacts/common/res/values-gu/strings.xml +++ b/java/com/android/contacts/common/res/values-gu/strings.xml @@ -261,5 +261,8 @@ "સેવાની શરતો" "ખુલ્લા સ્રોત લાઇસન્સીસ" "url ખોલવામાં નિષ્ફળ થયાં." - "વિડિઓ કૉલ કરો" + + + + diff --git a/java/com/android/contacts/common/res/values-hi/strings.xml b/java/com/android/contacts/common/res/values-hi/strings.xml index 736ce97f8747d2ba34cbf6b3948a7ed047c9a213..841a69021d7650cf1bd7dd8f85dde9ab68358864 100644 --- a/java/com/android/contacts/common/res/values-hi/strings.xml +++ b/java/com/android/contacts/common/res/values-hi/strings.xml @@ -261,5 +261,8 @@ "सेवा की शर्तें" "ओपन सोर्स लाइसेंस" "url खोलने में विफल रहा." - "वीडियो कॉल करें" + + + + diff --git a/java/com/android/contacts/common/res/values-hr/strings.xml b/java/com/android/contacts/common/res/values-hr/strings.xml index a65b73c5b11cb821571c1c8c303b1d66fed6f5fd..ece6fe789ede5f50b525cb4a6e737293cbac2e71 100644 --- a/java/com/android/contacts/common/res/values-hr/strings.xml +++ b/java/com/android/contacts/common/res/values-hr/strings.xml @@ -263,5 +263,8 @@ "Uvjeti pružanja usluge" "Licence otvorenog izvornog koda" "Otvaranje URL-a nije uspjelo." - "Upućivanje videopoziva" + + + + diff --git a/java/com/android/contacts/common/res/values-hu/strings.xml b/java/com/android/contacts/common/res/values-hu/strings.xml index 82c983b945b806d430b94042c6a8f8db5c1a807f..696ed1d1e83d695e8f1ed41856d7921210b08a7f 100644 --- a/java/com/android/contacts/common/res/values-hu/strings.xml +++ b/java/com/android/contacts/common/res/values-hu/strings.xml @@ -261,5 +261,8 @@ "Általános Szerződési Feltételek" "Nyílt forráskódú licencek" "Nem sikerült megnyitni az URL-címet." - "Videohívás indítása" + + + + diff --git a/java/com/android/contacts/common/res/values-hy/strings.xml b/java/com/android/contacts/common/res/values-hy/strings.xml index 384156e8662b68d648fa0615fe9eb10780ece354..1340a0efa59f2a3cd6e2168a05217435da03ca11 100644 --- a/java/com/android/contacts/common/res/values-hy/strings.xml +++ b/java/com/android/contacts/common/res/values-hy/strings.xml @@ -261,5 +261,8 @@ "Օգտագործման պայմաններ" "Բաց կոդով ծրագրակազմի արտոնագրեր" "Չհաջողվեց բացել url-ը:" - "Կատարել տեսազանգ" + + + + diff --git a/java/com/android/contacts/common/res/values-in/strings.xml b/java/com/android/contacts/common/res/values-in/strings.xml index d2f596d57277d86eae5eafb36422311965500a3c..17e54f00dfada51654501108585470d0ea10e4dc 100644 --- a/java/com/android/contacts/common/res/values-in/strings.xml +++ b/java/com/android/contacts/common/res/values-in/strings.xml @@ -261,5 +261,8 @@ "Persyaratan layanan" "Lisensi sumber terbuka" "Gagal membuka url." - "Lakukan video call" + + + + diff --git a/java/com/android/contacts/common/res/values-is/strings.xml b/java/com/android/contacts/common/res/values-is/strings.xml index 054dedf1d8f01fb73b8ada921c53f72ebd653c24..7fa50d674e5272a7947fd5691570f01c46d647fd 100644 --- a/java/com/android/contacts/common/res/values-is/strings.xml +++ b/java/com/android/contacts/common/res/values-is/strings.xml @@ -261,5 +261,8 @@ "Þjónustuskilmálar" "Leyfi opins kóða" "Ekki tókst að opna slóðina." - "Hringja myndsímtal" + + + + diff --git a/java/com/android/contacts/common/res/values-it/strings.xml b/java/com/android/contacts/common/res/values-it/strings.xml index 80ddf240901eb15797cb17ba1b0739799788ee5b..591ad851e95473db4af0ec97cc0dded64738c8e6 100644 --- a/java/com/android/contacts/common/res/values-it/strings.xml +++ b/java/com/android/contacts/common/res/values-it/strings.xml @@ -261,5 +261,8 @@ "Termini di servizio" "Licenze open source" "Impossibile aprire l\'URL." - "Effettua videochiamata" + + + + diff --git a/java/com/android/contacts/common/res/values-iw/strings.xml b/java/com/android/contacts/common/res/values-iw/strings.xml index b95998bae0cdc8a49a1396505f2c6ae13a688b8c..7ad55d88ef2597082b7f0d283622f15e9b8f9864 100644 --- a/java/com/android/contacts/common/res/values-iw/strings.xml +++ b/java/com/android/contacts/common/res/values-iw/strings.xml @@ -265,5 +265,8 @@ "תנאים והגבלות" "רישיונות קוד פתוח" "לא ניתן לפתוח את כתובת האתר." - "בצע שיחת וידאו" + + + + diff --git a/java/com/android/contacts/common/res/values-ja/strings.xml b/java/com/android/contacts/common/res/values-ja/strings.xml index 0135da0cecc25a155d9621e8899a4256b609dec4..2e7c5382e0872715a7f8e4fe5f0e34588421563e 100644 --- a/java/com/android/contacts/common/res/values-ja/strings.xml +++ b/java/com/android/contacts/common/res/values-ja/strings.xml @@ -261,5 +261,8 @@ "利用規約" "オープンソース ライセンス" "この URL を開けませんでした。" - "ビデオハングアウトを発信" + + + + diff --git a/java/com/android/contacts/common/res/values-ka/strings.xml b/java/com/android/contacts/common/res/values-ka/strings.xml index f126d4c81e7afb2ede8f05c3dc8b3800aeca0c43..26585942a43f9dbf038905f5f7a2a5c2116fb7fa 100644 --- a/java/com/android/contacts/common/res/values-ka/strings.xml +++ b/java/com/android/contacts/common/res/values-ka/strings.xml @@ -261,5 +261,8 @@ "მომსახურების პირობები" "ღია კოდის ლიცენზიები" "Url-ის გახსნა ვერ მოხერხდა." - "ვიდეოზარის განხორციელება" + + + + diff --git a/java/com/android/contacts/common/res/values-kk/strings.xml b/java/com/android/contacts/common/res/values-kk/strings.xml index 3d2e9bd696e5ff63074ec14c22630bab8c205ac0..47acf5e83bdbf0e14d8accba3e63d96f0f3981ac 100644 --- a/java/com/android/contacts/common/res/values-kk/strings.xml +++ b/java/com/android/contacts/common/res/values-kk/strings.xml @@ -261,5 +261,8 @@ "Қызмет көрсету шарттары" "Бастапқы коды ашық бағдарлама лицензиялары" "Url ашылған жоқ." - "Бейне қоңырау соғу" + + + + diff --git a/java/com/android/contacts/common/res/values-km/strings.xml b/java/com/android/contacts/common/res/values-km/strings.xml index 7715f401cc0c6ac783cd757331deadb098b39f70..98abe688211af356509f65a759c132815fa5ef33 100644 --- a/java/com/android/contacts/common/res/values-km/strings.xml +++ b/java/com/android/contacts/common/res/values-km/strings.xml @@ -261,5 +261,8 @@ "លក្ខខណ្ឌប្រើប្រាស់" "អាជ្ញាប័ណ្ណប្រភពកូដចំហ" "បាន​បរាជ័យ​ក្នុង​ការ​បើក URL។" - "ធ្វើការហៅជាវីដេអូ" + + + + diff --git a/java/com/android/contacts/common/res/values-kn/strings.xml b/java/com/android/contacts/common/res/values-kn/strings.xml index 8b8b3f2932a48f980ccaa2a032ae4b8858b12ff5..3dd4f5adabbc6bb92bb4d7c1032e33d5d8bf360e 100644 --- a/java/com/android/contacts/common/res/values-kn/strings.xml +++ b/java/com/android/contacts/common/res/values-kn/strings.xml @@ -261,5 +261,8 @@ "ಸೇವಾ ನಿಯಮಗಳು" "ಮುಕ್ತ ಮೂಲ ಪರವಾನಗಿಗಳು" "url ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ." - "ವೀಡಿಯೊ ಕರೆ ಮಾಡಿ" + + + + diff --git a/java/com/android/contacts/common/res/values-ko/strings.xml b/java/com/android/contacts/common/res/values-ko/strings.xml index a0eb767e5579b0f2b3c15158da71a54f0ad8481f..ccf1845bd6d6540cdbbfe7b5e72fe1045af79e8f 100644 --- a/java/com/android/contacts/common/res/values-ko/strings.xml +++ b/java/com/android/contacts/common/res/values-ko/strings.xml @@ -261,5 +261,8 @@ "서비스 약관" "오픈소스 라이선스" "URL을 열지 못했습니다." - "화상 통화 걸기" + + + + diff --git a/java/com/android/contacts/common/res/values-ky/strings.xml b/java/com/android/contacts/common/res/values-ky/strings.xml index 116da198d6e82c5fe556012bac02a49333b50a1e..c3309b7eec2d23aaf00d3b68d35044402d3cf186 100644 --- a/java/com/android/contacts/common/res/values-ky/strings.xml +++ b/java/com/android/contacts/common/res/values-ky/strings.xml @@ -261,5 +261,8 @@ "Тейлөө шарттары" "Ачык программа уруксаттамалары" "url ачылбай калды." - "Видео чалуу" + + + + diff --git a/java/com/android/contacts/common/res/values-lo/strings.xml b/java/com/android/contacts/common/res/values-lo/strings.xml index 68d485c9512fd04d4f39fea54ad616270442d113..ec684beeccc6191bc145b1d39984c4432d929585 100644 --- a/java/com/android/contacts/common/res/values-lo/strings.xml +++ b/java/com/android/contacts/common/res/values-lo/strings.xml @@ -261,5 +261,8 @@ "​ເງື່ອນ​ໄຂ​ການ​ໃຫ້​ບໍ​ລິ​ການ" "ລິຂະສິດໂອເພນຊອດ" "ເປີດ URL ລົ້ມເຫລວ." - "ເຮັດການໂທວິດີໂອ" + + + + diff --git a/java/com/android/contacts/common/res/values-lt/strings.xml b/java/com/android/contacts/common/res/values-lt/strings.xml index 15095f8ea23e280f839c94cec1f4fb193956e62e..082950a084f1bc1b3e1890921d8f9c409da5cde9 100644 --- a/java/com/android/contacts/common/res/values-lt/strings.xml +++ b/java/com/android/contacts/common/res/values-lt/strings.xml @@ -265,5 +265,8 @@ "Paslaugų teikimo sąlygos" "Atvirojo šaltinio licencijos" "Nepavyko atidaryti URL." - "Atlikti vaizdo skambutį" + + + + diff --git a/java/com/android/contacts/common/res/values-lv/strings.xml b/java/com/android/contacts/common/res/values-lv/strings.xml index feb575dd8f483cdf50b63251e0526d79a83e9c17..54a2481ea7942917cbe766b57a781a8b5fc05002 100644 --- a/java/com/android/contacts/common/res/values-lv/strings.xml +++ b/java/com/android/contacts/common/res/values-lv/strings.xml @@ -263,5 +263,8 @@ "Pakalpojumu sniegšanas noteikumi" "Atklātā pirmkoda licences" "Neizdevās atvērt URL." - "Sākt videozvanu" + + + + diff --git a/java/com/android/contacts/common/res/values-mk/strings.xml b/java/com/android/contacts/common/res/values-mk/strings.xml index b49f2a9e95a1bff660a1083d1e5510d2d6884935..060519fd819d70f981e4ae223dbda2a95743e659 100644 --- a/java/com/android/contacts/common/res/values-mk/strings.xml +++ b/java/com/android/contacts/common/res/values-mk/strings.xml @@ -261,5 +261,8 @@ "Услови на користење" "Лиценци за софтвер со отворен код" "Врската не успеа да се отвори." - "Воспостави видеоповик" + + + + diff --git a/java/com/android/contacts/common/res/values-ml/strings.xml b/java/com/android/contacts/common/res/values-ml/strings.xml index 5645d8667176a82c416113a50e5bf7a1a64ee18d..bd77e7ea2bdd78096451939aa6c6df80aacb1682 100644 --- a/java/com/android/contacts/common/res/values-ml/strings.xml +++ b/java/com/android/contacts/common/res/values-ml/strings.xml @@ -261,5 +261,8 @@ "സേവന നിബന്ധനകൾ" "ഓപ്പൺ സോഴ്‌സ് ലൈസൻസ്" "url തുറക്കാനായില്ല." - "വീഡിയോ കോൾ ചെയ്യുക" + + + + diff --git a/java/com/android/contacts/common/res/values-mn/strings.xml b/java/com/android/contacts/common/res/values-mn/strings.xml index b8c5dbbc384c3f608168698c48e0c20afcb20e99..e6e1ab12a6cd2f403a3349e7c1a54db27a9a4f54 100644 --- a/java/com/android/contacts/common/res/values-mn/strings.xml +++ b/java/com/android/contacts/common/res/values-mn/strings.xml @@ -261,5 +261,8 @@ "Үйлчилгээний нөхцөл" "Нээлттэй эхийн лиценз" "URL-г нээж чадсангүй." - "Видео дуудлага хийх" + + + + diff --git a/java/com/android/contacts/common/res/values-mr/strings.xml b/java/com/android/contacts/common/res/values-mr/strings.xml index 72e52823bffc79778ecf0716dda33ae0fa856865..52b989fe9a0dc9b0fa590144d4e32c324d84f4bb 100644 --- a/java/com/android/contacts/common/res/values-mr/strings.xml +++ b/java/com/android/contacts/common/res/values-mr/strings.xml @@ -261,5 +261,8 @@ "सेवा अटी" "मुक्त स्त्रोत परवाने" "url उघडण्यात अयशस्वी झाले." - "व्हिडिओ कॉल करा" + + + + diff --git a/java/com/android/contacts/common/res/values-ms/strings.xml b/java/com/android/contacts/common/res/values-ms/strings.xml index 91cf2de87254529e9fc1f166216f7e247abc7529..c3ae12a923e3eb26ea1182d7f9774004f29d6b31 100644 --- a/java/com/android/contacts/common/res/values-ms/strings.xml +++ b/java/com/android/contacts/common/res/values-ms/strings.xml @@ -261,5 +261,8 @@ "Syarat perkhidmatan" "Lesen sumber terbuka" "Gagal membuka url." - "Buat panggilan video" + + + + diff --git a/java/com/android/contacts/common/res/values-my/strings.xml b/java/com/android/contacts/common/res/values-my/strings.xml index e162b0cf7a68dac2e509da7730f4f8da9a031667..3a90758d537fe786dab9a4c4e239eb90cb402839 100644 --- a/java/com/android/contacts/common/res/values-my/strings.xml +++ b/java/com/android/contacts/common/res/values-my/strings.xml @@ -261,5 +261,8 @@ "ဝန်ဆောင်မှုဆိုင်ရာ စည်းမျဉ်းများ" "အခမဲ့ရင်းမြစ်လိုင်စင်များ" "url ကို ဖွင့်၍မရပါ။" - "ဗီဒီယို ခေါ်ဆိုမှုကို ပြုလုပ်ပါ" + + + + diff --git a/java/com/android/contacts/common/res/values-nb/strings.xml b/java/com/android/contacts/common/res/values-nb/strings.xml index 930e949fd208cb92f9e32fae138ee6218cb3d8d7..ab1fd57d41c3583a05e22968a33873363b2f8603 100644 --- a/java/com/android/contacts/common/res/values-nb/strings.xml +++ b/java/com/android/contacts/common/res/values-nb/strings.xml @@ -261,5 +261,8 @@ "Vilkår for bruk" "Lisenser for åpen kildekode" "Kunne ikke åpne nettadressen." - "Start et videoanrop" + + + + diff --git a/java/com/android/contacts/common/res/values-ne/strings.xml b/java/com/android/contacts/common/res/values-ne/strings.xml index 50b44fdb7377ef65c328e2d1c19fd1ba66ae2ba9..1d3e5a2b32ac92f2a2491d0810eb4beaff498dea 100644 --- a/java/com/android/contacts/common/res/values-ne/strings.xml +++ b/java/com/android/contacts/common/res/values-ne/strings.xml @@ -261,5 +261,8 @@ "सेवा सर्तहरू" "खुला स्रोत सम्बन्धी इजाजतपत्रहरू" "url खोल्न सकिएन।" - "भिडियो कल गर्नुहोस्" + + + + diff --git a/java/com/android/contacts/common/res/values-nl/strings.xml b/java/com/android/contacts/common/res/values-nl/strings.xml index cfeb7dfa4c10188a697a822ac6d1ad8980838561..fb7d571dc6cc35195662f2a4cf37066a18dcd282 100644 --- a/java/com/android/contacts/common/res/values-nl/strings.xml +++ b/java/com/android/contacts/common/res/values-nl/strings.xml @@ -261,5 +261,8 @@ "Servicevoorwaarden" "Open-sourcelicenties" "Kan de URL niet openen." - "Videogesprek starten" + + + + diff --git a/java/com/android/contacts/common/res/values-no/strings.xml b/java/com/android/contacts/common/res/values-no/strings.xml index 930e949fd208cb92f9e32fae138ee6218cb3d8d7..ab1fd57d41c3583a05e22968a33873363b2f8603 100644 --- a/java/com/android/contacts/common/res/values-no/strings.xml +++ b/java/com/android/contacts/common/res/values-no/strings.xml @@ -261,5 +261,8 @@ "Vilkår for bruk" "Lisenser for åpen kildekode" "Kunne ikke åpne nettadressen." - "Start et videoanrop" + + + + diff --git a/java/com/android/contacts/common/res/values-pa/strings.xml b/java/com/android/contacts/common/res/values-pa/strings.xml index c043ab7d09ffe4bfe97379bfd157b5659b7239e6..fef6578b040205b113a291259792955cf7f2f805 100644 --- a/java/com/android/contacts/common/res/values-pa/strings.xml +++ b/java/com/android/contacts/common/res/values-pa/strings.xml @@ -261,5 +261,8 @@ "ਸੇਵਾ ਦੀਆਂ ਮਦਾਂ" "ਖੁੱਲ੍ਹਾ ਸਰੋਤ ਲਾਇਸੰਸ" "url ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ।" - "ਵੀਡੀਓ ਕਾਲ ਕਰੋ" + + + + diff --git a/java/com/android/contacts/common/res/values-pl/strings.xml b/java/com/android/contacts/common/res/values-pl/strings.xml index f48e2ce38e9aca5b72a84484234906cb0ec958a5..c2268d492a36d426812cc2f47942fa3a99649d1e 100644 --- a/java/com/android/contacts/common/res/values-pl/strings.xml +++ b/java/com/android/contacts/common/res/values-pl/strings.xml @@ -265,5 +265,8 @@ "Warunki usługi" "Licencje open source" "Nie udało się otworzyć URL-a." - "Rozpocznij rozmowę wideo" + + + + diff --git a/java/com/android/contacts/common/res/values-pt-rBR/strings.xml b/java/com/android/contacts/common/res/values-pt-rBR/strings.xml index 1dbdce9667ed24b3c016bece7878ca6a9cb77850..4ab169e919675b2645f3a77843f759d31baabfb8 100644 --- a/java/com/android/contacts/common/res/values-pt-rBR/strings.xml +++ b/java/com/android/contacts/common/res/values-pt-rBR/strings.xml @@ -261,5 +261,8 @@ "Termos de Serviço" "Licenças de código aberto" "Falha ao abrir o URL." - "Realizar videochamada" + + + + diff --git a/java/com/android/contacts/common/res/values-pt-rPT/strings.xml b/java/com/android/contacts/common/res/values-pt-rPT/strings.xml index 08fe820d759403f7a6aa446add3828c31c28d95a..f979fdc3e35f401172c349d1127745901d225c24 100644 --- a/java/com/android/contacts/common/res/values-pt-rPT/strings.xml +++ b/java/com/android/contacts/common/res/values-pt-rPT/strings.xml @@ -261,5 +261,8 @@ "Termos de Utilização" "Licenças de código aberto" "Falha ao abrir o URL." - "Efetuar videochamada" + + + + diff --git a/java/com/android/contacts/common/res/values-pt/strings.xml b/java/com/android/contacts/common/res/values-pt/strings.xml index 1dbdce9667ed24b3c016bece7878ca6a9cb77850..4ab169e919675b2645f3a77843f759d31baabfb8 100644 --- a/java/com/android/contacts/common/res/values-pt/strings.xml +++ b/java/com/android/contacts/common/res/values-pt/strings.xml @@ -261,5 +261,8 @@ "Termos de Serviço" "Licenças de código aberto" "Falha ao abrir o URL." - "Realizar videochamada" + + + + diff --git a/java/com/android/contacts/common/res/values-ro/strings.xml b/java/com/android/contacts/common/res/values-ro/strings.xml index 0f1b98d81b3cab44cc9fb0ed7a517df45194f585..ae2ea6599131735c154fe9fa636f69934937a43f 100644 --- a/java/com/android/contacts/common/res/values-ro/strings.xml +++ b/java/com/android/contacts/common/res/values-ro/strings.xml @@ -263,5 +263,8 @@ "Termeni și condiții" "Licențe open source" "Adresa URL nu a putut fi deschisă." - "Efectuați un apel video" + + + + diff --git a/java/com/android/contacts/common/res/values-ru/strings.xml b/java/com/android/contacts/common/res/values-ru/strings.xml index a75cc6400dca06b62653322bad70a2c3e6c526eb..eaa9983352bdf28927755afe64327d4640921f3c 100644 --- a/java/com/android/contacts/common/res/values-ru/strings.xml +++ b/java/com/android/contacts/common/res/values-ru/strings.xml @@ -265,5 +265,8 @@ "Условия использования" "Лицензии открытого ПО" "Не удалось открыть URL." - "Видеовызов" + + + + diff --git a/java/com/android/contacts/common/res/values-si/strings.xml b/java/com/android/contacts/common/res/values-si/strings.xml index 42a851723ecd7cffc06ac2ee6bc992df6e7483ad..238bcfee13e8ef4e903e3cfa5caec3c954c6895b 100644 --- a/java/com/android/contacts/common/res/values-si/strings.xml +++ b/java/com/android/contacts/common/res/values-si/strings.xml @@ -261,5 +261,8 @@ "සේවා නියම" "විවෘත මූලාශ්‍ර බලපත්‍ර" "url විවෘත කිරීමට අසමත් විය." - "වීඩියෝ ඇමතුම සිදු කිරීම" + + + + diff --git a/java/com/android/contacts/common/res/values-sk/strings.xml b/java/com/android/contacts/common/res/values-sk/strings.xml index 22e47bfacf790f8f0babb4e65ba9efcf74b8de30..6daafb7b0a3f9450de32e657f9e8cb4b1f5ef3fa 100644 --- a/java/com/android/contacts/common/res/values-sk/strings.xml +++ b/java/com/android/contacts/common/res/values-sk/strings.xml @@ -265,5 +265,8 @@ "Zmluvné podmienky" "Licencie open source" "Webovú adresu nebolo možné otvoriť" - "Uskutočniť videohovor" + + + + diff --git a/java/com/android/contacts/common/res/values-sl/strings.xml b/java/com/android/contacts/common/res/values-sl/strings.xml index f2826c6d13ad4c2a42cd360ab9e3adfe24f895d9..964bac24c74e01f763df0609898f530357c998e6 100644 --- a/java/com/android/contacts/common/res/values-sl/strings.xml +++ b/java/com/android/contacts/common/res/values-sl/strings.xml @@ -265,5 +265,8 @@ "Pogoji storitve" "Odprtokodne licence" "Naslova URL ni bilo mogoče odpreti." - "Začetek videoklica" + + + + diff --git a/java/com/android/contacts/common/res/values-sq/strings.xml b/java/com/android/contacts/common/res/values-sq/strings.xml index 83920fa1201cd4f597831bd8eed76a6c526f7eee..d46841b4b0a4a4ad12ce5adfad10db851ad3b462 100644 --- a/java/com/android/contacts/common/res/values-sq/strings.xml +++ b/java/com/android/contacts/common/res/values-sq/strings.xml @@ -261,5 +261,8 @@ "Kushtet e shërbimit" "Licencat me burim të hapur" "Dështoi në hapjen e url-së." - "Kryej një telefonatë me video" + + + + diff --git a/java/com/android/contacts/common/res/values-sr/strings.xml b/java/com/android/contacts/common/res/values-sr/strings.xml index 9801a29a3569893bb878e18e25402b99b3db4eda..6151ef960161e80c1e1a4313d74a6d9b60768d38 100644 --- a/java/com/android/contacts/common/res/values-sr/strings.xml +++ b/java/com/android/contacts/common/res/values-sr/strings.xml @@ -263,5 +263,8 @@ "Услови коришћења услуге" "Лиценце отвореног кода" "Отварање URL-а није успело." - "Упути видео позив" + + + + diff --git a/java/com/android/contacts/common/res/values-sv/strings.xml b/java/com/android/contacts/common/res/values-sv/strings.xml index 9fa33bee8605949dddadf8b72783a155cd050aa4..94f7abd35a105021f7be730de23304a95ee0e84a 100644 --- a/java/com/android/contacts/common/res/values-sv/strings.xml +++ b/java/com/android/contacts/common/res/values-sv/strings.xml @@ -261,5 +261,8 @@ "Användarvillkor" "Licenser för öppen källkod" "Det gick inte att öppna webbadressen." - "Ring ett videosamtal" + + + + diff --git a/java/com/android/contacts/common/res/values-sw/strings.xml b/java/com/android/contacts/common/res/values-sw/strings.xml index 43e81e500570ddbc2ab9bb528facf8af7ec968ce..717f1b87ede840dd9db07a474ff2ecaa837ab178 100644 --- a/java/com/android/contacts/common/res/values-sw/strings.xml +++ b/java/com/android/contacts/common/res/values-sw/strings.xml @@ -261,5 +261,8 @@ "Sheria na masharti" "Leseni za programu huria" "Imeshindwa kufungua url." - "Anzisha Hangout ya Video" + + + + diff --git a/java/com/android/contacts/common/res/values-ta/strings.xml b/java/com/android/contacts/common/res/values-ta/strings.xml index 6a66f60cd21671250b188c7105f4df8790e17d3b..0bbee79f774a62646fc4b4b1b8cb8dd7fa630366 100644 --- a/java/com/android/contacts/common/res/values-ta/strings.xml +++ b/java/com/android/contacts/common/res/values-ta/strings.xml @@ -261,5 +261,8 @@ "சேவை விதிமுறைகள்" "ஓப்பன் சோர்ஸ் உரிமங்கள்" "urlஐத் திறக்க முடியவில்லை." - "வீடியோ அழைப்பைச் செய்" + + + + diff --git a/java/com/android/contacts/common/res/values-te/strings.xml b/java/com/android/contacts/common/res/values-te/strings.xml index 59acd5b17ca4b5e35951b03a7519a6d2745fcb0e..474bb935943a21e7d602a350823cd4cea0ebe56a 100644 --- a/java/com/android/contacts/common/res/values-te/strings.xml +++ b/java/com/android/contacts/common/res/values-te/strings.xml @@ -261,5 +261,8 @@ "సేవా నిబంధనలు" "ఓపెన్ సోర్స్ లైసెన్స్‌లు" "urlని తెరవడంలో విఫలమైంది." - "వీడియో కాల్ చేస్తుంది" + + + + diff --git a/java/com/android/contacts/common/res/values-th/strings.xml b/java/com/android/contacts/common/res/values-th/strings.xml index 0585fba9f199683a68aa59d78eaf7bde0cc79ca5..598b810b4794502d37651fd77d22a1b75defb350 100644 --- a/java/com/android/contacts/common/res/values-th/strings.xml +++ b/java/com/android/contacts/common/res/values-th/strings.xml @@ -261,5 +261,8 @@ "ข้อกำหนดในการให้บริการ" "ใบอนุญาตโอเพนซอร์ส" "เปิด URL ไม่สำเร็จ" - "เริ่มแฮงเอาท์วิดีโอ" + + + + diff --git a/java/com/android/contacts/common/res/values-tl/strings.xml b/java/com/android/contacts/common/res/values-tl/strings.xml index 49a2830a80ab8779d3f80b0a416769d3cc5389cd..fd51f1f2a1056a7600cde1901b9829978bff3bf1 100644 --- a/java/com/android/contacts/common/res/values-tl/strings.xml +++ b/java/com/android/contacts/common/res/values-tl/strings.xml @@ -261,5 +261,8 @@ "Tuntunin ng serbisyo" "Mga open source na lisensya" "Nabigong buksan ang url." - "Magsimula ng video call" + + + + diff --git a/java/com/android/contacts/common/res/values-tr/strings.xml b/java/com/android/contacts/common/res/values-tr/strings.xml index b0d4a91aac6156178b12b5b86ac693ab4913e9c6..20b076e2e9741711f2fdbe12a93217c9a247616c 100644 --- a/java/com/android/contacts/common/res/values-tr/strings.xml +++ b/java/com/android/contacts/common/res/values-tr/strings.xml @@ -261,5 +261,8 @@ "Hizmet şartları" "Açık kaynak lisansları" "URL açılamadı." - "Video görüşmesi yap" + + + + diff --git a/java/com/android/contacts/common/res/values-uk/strings.xml b/java/com/android/contacts/common/res/values-uk/strings.xml index fe936d5cf215ff866b47f1e25a5953e8621c640a..2e9c3cb8490e634341f48f38470f3047264e6220 100644 --- a/java/com/android/contacts/common/res/values-uk/strings.xml +++ b/java/com/android/contacts/common/res/values-uk/strings.xml @@ -265,5 +265,8 @@ "Умови використання" "Ліцензії на ПЗ з відкритим кодом" "Не вдалося відкрити посилання." - "Почати відеодзвінок" + + + + diff --git a/java/com/android/contacts/common/res/values-ur/strings.xml b/java/com/android/contacts/common/res/values-ur/strings.xml index 3273fb2ef243e086bb313535f56553d210c3a936..8db576e081612850004f423aca40853abac7c9d4 100644 --- a/java/com/android/contacts/common/res/values-ur/strings.xml +++ b/java/com/android/contacts/common/res/values-ur/strings.xml @@ -261,5 +261,8 @@ "سروس کی شرائط" "اوپن سورس لائسنسز" "‏URL کھولنے میں ناکامی۔" - "ویڈیو کال کریں" + + + + diff --git a/java/com/android/contacts/common/res/values-uz/strings.xml b/java/com/android/contacts/common/res/values-uz/strings.xml index 93fc0841d48d77823d434c1329ce622be926ffbd..9fe0e508682e49424fb1a3c3a95ded1d013e028c 100644 --- a/java/com/android/contacts/common/res/values-uz/strings.xml +++ b/java/com/android/contacts/common/res/values-uz/strings.xml @@ -261,5 +261,8 @@ "Foydalanish shartlari" "Ochiq kodli dasturiy ta’minot litsenziyalari" "URLni ochishda xatolik yuz berdi." - "Video qo‘ng‘iroq qilish" + + + + diff --git a/java/com/android/contacts/common/res/values-vi/strings.xml b/java/com/android/contacts/common/res/values-vi/strings.xml index c444245b1b3d2b9985ece8e60bde6893aeecc1f3..3a6f5947358d040116440404d1d5c360968671c4 100644 --- a/java/com/android/contacts/common/res/values-vi/strings.xml +++ b/java/com/android/contacts/common/res/values-vi/strings.xml @@ -261,5 +261,8 @@ "Điều khoản dịch vụ" "Giấy phép nguồn mở" "Không mở được url." - "Gọi điện video" + + + + diff --git a/java/com/android/contacts/common/res/values-zh-rCN/strings.xml b/java/com/android/contacts/common/res/values-zh-rCN/strings.xml index 764664bb033279f3b041ef039a38216fc9c80451..89c8e8d0dcc3f9ae73ebc1ca8d2470065c2b4dcb 100644 --- a/java/com/android/contacts/common/res/values-zh-rCN/strings.xml +++ b/java/com/android/contacts/common/res/values-zh-rCN/strings.xml @@ -261,5 +261,8 @@ "服务条款" "开放源代码许可" "无法打开网址。" - "发起视频通话" + + + + diff --git a/java/com/android/contacts/common/res/values-zh-rHK/strings.xml b/java/com/android/contacts/common/res/values-zh-rHK/strings.xml index 8c37a02b9ad0f69c765cf6f073fded55e432b260..bd912b6ffa864838a65f848318aa5e5ff509652a 100644 --- a/java/com/android/contacts/common/res/values-zh-rHK/strings.xml +++ b/java/com/android/contacts/common/res/values-zh-rHK/strings.xml @@ -261,5 +261,8 @@ "服務條款" "開放原始碼授權" "無法開啟網址。" - "開始視像通話" + + + + diff --git a/java/com/android/contacts/common/res/values-zh-rTW/strings.xml b/java/com/android/contacts/common/res/values-zh-rTW/strings.xml index 015683eb02cd9fdb161fa5eee838bf978a3d87ff..14e1e901f674f61a6c9b2da4528d03323206d506 100644 --- a/java/com/android/contacts/common/res/values-zh-rTW/strings.xml +++ b/java/com/android/contacts/common/res/values-zh-rTW/strings.xml @@ -261,5 +261,8 @@ "服務條款" "開放原始碼授權" "無法開啟網址。" - "撥打視訊通話" + + + + diff --git a/java/com/android/contacts/common/res/values-zu/strings.xml b/java/com/android/contacts/common/res/values-zu/strings.xml index f128b2a2a661197b60ab4d70658712462905f2bd..1c93e4c118df9bdc91b4af48f6ded2fd153ab4ed 100644 --- a/java/com/android/contacts/common/res/values-zu/strings.xml +++ b/java/com/android/contacts/common/res/values-zu/strings.xml @@ -261,5 +261,8 @@ "Imigomo yesevisi" "Amalayisense womthombo ovulekile" "Yehlulekile ukuvula i-url." - "Yenza ikholi yevidiyo" + + + + diff --git a/java/com/android/contacts/common/res/values/colors.xml b/java/com/android/contacts/common/res/values/colors.xml index 7524eff584e50a10bc61f696566e11f8af8385e3..434d193c73e5b34b91de948becb3149044b92050 100644 --- a/java/com/android/contacts/common/res/values/colors.xml +++ b/java/com/android/contacts/common/res/values/colors.xml @@ -20,6 +20,8 @@ #44ff0000 + #A52714 + #a0ffffff diff --git a/java/com/android/contacts/common/res/values/strings.xml b/java/com/android/contacts/common/res/values/strings.xml index d587870876515a279700542668c173d6b0c63e9d..9ac9fef28adb47c4f6925968f27eea55231531d2 100644 --- a/java/com/android/contacts/common/res/values/strings.xml +++ b/java/com/android/contacts/common/res/values/strings.xml @@ -791,5 +791,12 @@ This is especially valuable for views without textual representation like ImageView. [CHAR LIMIT=NONE]--> - Place video call + Video call + + + Share and call diff --git a/java/com/android/contacts/common/widget/FloatingActionButtonController.java b/java/com/android/contacts/common/widget/FloatingActionButtonController.java index 368d09207394c9487bbfc967c39c8377d8e3c10f..d924681eac5cc77d369d43d18d580f996779dfe4 100644 --- a/java/com/android/contacts/common/widget/FloatingActionButtonController.java +++ b/java/com/android/contacts/common/widget/FloatingActionButtonController.java @@ -72,12 +72,16 @@ public class FloatingActionButtonController { } /** - * Sets FAB as View.VISIBLE or View.GONE. + * Sets FAB as shown or hidden. * * @param visible Whether or not to make the container visible. */ public void setVisible(boolean visible) { - mFab.setVisibility(visible ? View.VISIBLE : View.GONE); + if (visible) { + mFab.show(); + } else { + mFab.hide(); + } } public void changeIcon(Drawable icon, String description) { diff --git a/java/com/android/dialer/about/AboutPhoneFragment.java b/java/com/android/dialer/about/AboutPhoneFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..ecd7c0f76badd3ed484faf5a313c175f8a52c9b5 --- /dev/null +++ b/java/com/android/dialer/about/AboutPhoneFragment.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2017 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.dialer.about; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.text.TextUtils; + +/** The fragment for information about the Phone App */ +public class AboutPhoneFragment extends PreferenceFragment { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.about_phone_fragment); + + // We set the intent here, instead of in XML, to avoid specifying a target package, which + // differs between AOSP and the GoogleDialer. + Intent openSourceActivity = + new Intent(getActivity().getApplicationContext(), LicenseMenuActivity.class); + findPreference(getString(R.string.open_source_licenses_key)).setIntent(openSourceActivity); + populateBuildVersion(); + } + + private void populateBuildVersion() { + Preference buildVersion = findPreference(getResources().getString(R.string.build_version_key)); + String versionName = getVersionName(); + if (!TextUtils.isEmpty(versionName)) { + buildVersion.setSummary(versionName); + } + } + + private String getVersionName() { + Context context = getContext(); + try { + return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; + } catch (NameNotFoundException e) { + return ""; + } + } + + @Override + public Context getContext() { + return getActivity(); + } +} diff --git a/java/com/android/dialer/about/AndroidManifest.xml b/java/com/android/dialer/about/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9489ce1ea6fff7526ec0a61dfb2f138c986ab1d --- /dev/null +++ b/java/com/android/dialer/about/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/java/com/android/dialer/about/License.java b/java/com/android/dialer/about/License.java new file mode 100644 index 0000000000000000000000000000000000000000..d0d73b8e17a772fd05871ce251ae77baf5576578 --- /dev/null +++ b/java/com/android/dialer/about/License.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017 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.dialer.about; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Container class to store the name of a library and the filename of its associated license file. + */ +public final class License implements Comparable, Parcelable { + // Name of the third-party library. + private final String libraryName; + // Byte offset in the file to the start of the license text. + private final long licenseOffset; + // Byte length of the license text. + private final int licenseLength; + + /** + * Create an object representing a stored license. The text for all licenses is stored in a single + * file, so the offset and length describe this license's position within the file. + */ + static License create(String libraryName, long licenseOffset, int licenseLength) { + return new License(libraryName, licenseOffset, licenseLength); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public License createFromParcel(Parcel in) { + return new License(in); + } + + @Override + public License[] newArray(int size) { + return new License[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(libraryName); + dest.writeLong(licenseOffset); + dest.writeInt(licenseLength); + } + + @Override + public int compareTo(License o) { + return libraryName.compareToIgnoreCase(o.getLibraryName()); + } + + @Override + public String toString() { + return getLibraryName(); + } + + private License(String libraryName, long licenseOffset, int licenseLength) { + this.libraryName = libraryName; + this.licenseOffset = licenseOffset; + this.licenseLength = licenseLength; + } + + private License(Parcel in) { + libraryName = in.readString(); + licenseOffset = in.readLong(); + licenseLength = in.readInt(); + } + + String getLibraryName() { + return libraryName; + } + + long getLicenseOffset() { + return licenseOffset; + } + + int getLicenseLength() { + return licenseLength; + } +} diff --git a/java/com/android/dialer/about/LicenseActivity.java b/java/com/android/dialer/about/LicenseActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..24822235fd5700c9075f99d5d33fcbe1b46a8f06 --- /dev/null +++ b/java/com/android/dialer/about/LicenseActivity.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2017 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.dialer.about; + +import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; +import android.view.MenuItem; +import android.widget.ScrollView; +import android.widget.TextView; + +/** Simple Activity that renders locally stored open source legal info in a text view. */ +public final class LicenseActivity extends ActionBarActivity { + private static final String TAG = "LicenseActivity"; + private static final String STATE_SCROLL_POS = "scroll_pos"; + + @Override + public void onCreate(Bundle bundle) { + super.onCreate(bundle); + setContentView(R.layout.license_scrollview); + + License license = getIntent().getParcelableExtra(LicenseMenuActivity.ARGS_LICENSE); + getSupportActionBar().setTitle(license.getLibraryName()); + + // Show 'up' button with no logo. + getSupportActionBar().setDisplayShowHomeEnabled(true); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setLogo(null); + + TextView textView = (TextView) findViewById(R.id.license_activity_textview); + String licenseText = Licenses.getLicenseText(this, license); + if (licenseText == null) { + finish(); + return; + } + textView.setText(licenseText); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + ScrollView scrollView = (ScrollView) findViewById(R.id.license_activity_scrollview); + TextView textView = (TextView) findViewById(R.id.license_activity_textview); + int firstVisibleLine = textView.getLayout().getLineForVertical(scrollView.getScrollY()); + int firstVisibleChar = textView.getLayout().getLineStart(firstVisibleLine); + outState.putInt(STATE_SCROLL_POS, firstVisibleChar); + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + final ScrollView scrollView = (ScrollView) findViewById(R.id.license_activity_scrollview); + final int firstVisibleChar = savedInstanceState.getInt(STATE_SCROLL_POS); + scrollView.post( + new Runnable() { + @Override + public void run() { + TextView textView = (TextView) findViewById(R.id.license_activity_textview); + int firstVisibleLine = textView.getLayout().getLineForOffset(firstVisibleChar); + int offset = textView.getLayout().getLineTop(firstVisibleLine); + scrollView.scrollTo(0, offset); + } + }); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/java/com/android/dialer/about/LicenseLoader.java b/java/com/android/dialer/about/LicenseLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..50d6834d92a392853aa8eba0cde0f20a31cbde79 --- /dev/null +++ b/java/com/android/dialer/about/LicenseLoader.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 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.dialer.about; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; +import java.util.List; + +/** {@link AsyncTaskLoader} to load the list of licenses for the license menu activity. */ +final class LicenseLoader extends AsyncTaskLoader> { + + private List licenses; + + LicenseLoader(Context context) { + // This must only pass the application context to avoid leaking a pointer to the Activity. + super(context.getApplicationContext()); + } + + @Override + public List loadInBackground() { + return Licenses.getLicenses(getContext()); + } + + @Override + public void deliverResult(List licenses) { + this.licenses = licenses; + super.deliverResult(licenses); + } + + @Override + protected void onStartLoading() { + if (licenses != null) { + deliverResult(licenses); + } else { + forceLoad(); + } + } + + @Override + protected void onStopLoading() { + cancelLoad(); + } +} diff --git a/java/com/android/dialer/about/LicenseMenuActivity.java b/java/com/android/dialer/about/LicenseMenuActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..73047989cdf45580af01de322fd3d7d2f6e02372 --- /dev/null +++ b/java/com/android/dialer/about/LicenseMenuActivity.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2017 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.dialer.about; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; +import android.support.v7.app.ActionBarActivity; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import java.util.ArrayList; +import java.util.List; + +/** An Activity listing third party libraries with notice licenses. */ +public final class LicenseMenuActivity extends ActionBarActivity + implements LoaderCallbacks> { + + static final String ARGS_LICENSE = "license"; + + private static final int LOADER_ID = 54321; + + private ArrayAdapter listAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.license_menu_activity); + + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + listAdapter = new ArrayAdapter<>(this, R.layout.license, R.id.license, new ArrayList<>()); + getSupportLoaderManager().initLoader(LOADER_ID, null, this); + ListView listView = (ListView) findViewById(R.id.license_list); + listView.setAdapter(listAdapter); + listView.setOnItemClickListener( + new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + License license = (License) parent.getItemAtPosition(position); + Intent licenseIntent = new Intent(LicenseMenuActivity.this, LicenseActivity.class); + licenseIntent.putExtra(ARGS_LICENSE, license); + startActivity(licenseIntent); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + // Go back one place in the history stack, if the app icon is clicked. + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onDestroy() { + super.onDestroy(); + getSupportLoaderManager().destroyLoader(LOADER_ID); + } + + @Override + public Loader> onCreateLoader(int id, Bundle args) { + return new LicenseLoader(this); + } + + @Override + public void onLoadFinished(Loader> loader, List licenses) { + listAdapter.clear(); + listAdapter.addAll(licenses); + listAdapter.notifyDataSetChanged(); + } + + @Override + public void onLoaderReset(Loader> loader) { + listAdapter.clear(); + listAdapter.notifyDataSetChanged(); + } +} diff --git a/java/com/android/dialer/about/Licenses.java b/java/com/android/dialer/about/Licenses.java new file mode 100644 index 0000000000000000000000000000000000000000..d90c282b667596a392d5a39bfe1ca6c61c4c3b6c --- /dev/null +++ b/java/com/android/dialer/about/Licenses.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2017 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.dialer.about; + +import android.content.Context; +import android.content.res.Resources; +import com.android.dialer.common.Assert; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; + +/** A helper for extracting licenses. */ +public final class Licenses { + private static final String TAG = "Licenses"; + private static final String LICENSE_FILENAME = "third_party_licenses"; + private static final String LICENSE_METADATA_FILENAME = "third_party_license_metadata"; + + /** Return the licenses bundled into this app. */ + public static ArrayList getLicenses(Context context) { + return getLicenseListFromMetadata( + getTextFromResource(context.getApplicationContext(), LICENSE_METADATA_FILENAME, 0, -1)); + } + + /** + * Returns a list of {@link License}s parsed from a license metadata file. + * + * @param metadata a {@code String} containing the contents of a license metadata file. + */ + private static ArrayList getLicenseListFromMetadata(String metadata) { + String[] entries = metadata.split("\n"); + ArrayList licenses = new ArrayList(entries.length); + for (String entry : entries) { + int delimiter = entry.indexOf(' '); + String[] licenseLocation = entry.substring(0, delimiter).split(":"); + Assert.checkState( + delimiter > 0 && licenseLocation.length == 2, + "Invalid license meta-data line:\n" + entry); + long licenseOffset = Long.parseLong(licenseLocation[0]); + int licenseLength = Integer.parseInt(licenseLocation[1]); + licenses.add(License.create(entry.substring(delimiter + 1), licenseOffset, licenseLength)); + } + Collections.sort(licenses); + return licenses; + } + + /** Return the text of a bundled license file. */ + public static String getLicenseText(Context context, License license) { + long offset = license.getLicenseOffset(); + int length = license.getLicenseLength(); + return getTextFromResource(context, LICENSE_FILENAME, offset, length); + } + + private static String getTextFromResource( + Context context, String filename, long offset, int length) { + Resources resources = context.getApplicationContext().getResources(); + // When aapt is called with --rename-manifest-package, the package name is changed for the + // application, but not for the resources. This is to find the package name of a known + // resource to know what package to lookup the license files in. + String packageName = resources.getResourcePackageName(R.id.dummy_placeholder); + InputStream stream = + resources.openRawResource(resources.getIdentifier(filename, "raw", packageName)); + return getTextFromInputStream(stream, offset, length); + } + + private static String getTextFromInputStream(InputStream stream, long offset, int length) { + byte[] buffer = new byte[1024]; + ByteArrayOutputStream textArray = new ByteArrayOutputStream(); + + try { + stream.skip(offset); + int bytesRemaining = length > 0 ? length : Integer.MAX_VALUE; + int bytes = 0; + + while (bytesRemaining > 0 + && (bytes = stream.read(buffer, 0, Math.min(bytesRemaining, buffer.length))) != -1) { + textArray.write(buffer, 0, bytes); + bytesRemaining -= bytes; + } + stream.close(); + } catch (IOException e) { + throw new RuntimeException("Failed to read license or metadata text.", e); + } + try { + return textArray.toString("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Unsupported encoding UTF8. This should always be supported.", e); + } + } +} diff --git a/java/com/android/dialer/about/res/layout/dummy_placeholder.xml b/java/com/android/dialer/about/res/layout/dummy_placeholder.xml new file mode 100644 index 0000000000000000000000000000000000000000..6d867ef555fabf76905f379e4ff77911f27dcaf7 --- /dev/null +++ b/java/com/android/dialer/about/res/layout/dummy_placeholder.xml @@ -0,0 +1,21 @@ + + + + diff --git a/java/com/android/dialer/about/res/layout/license.xml b/java/com/android/dialer/about/res/layout/license.xml new file mode 100644 index 0000000000000000000000000000000000000000..ef67982a16f93635f07f387784702255a931add8 --- /dev/null +++ b/java/com/android/dialer/about/res/layout/license.xml @@ -0,0 +1,40 @@ + + + + + + + diff --git a/java/com/android/dialer/about/res/layout/license_menu_activity.xml b/java/com/android/dialer/about/res/layout/license_menu_activity.xml new file mode 100644 index 0000000000000000000000000000000000000000..8ed47bf68ce5c269a1eb0b1dea6d962978a043cc --- /dev/null +++ b/java/com/android/dialer/about/res/layout/license_menu_activity.xml @@ -0,0 +1,35 @@ + + + + + diff --git a/java/com/android/dialer/about/res/layout/license_scrollview.xml b/java/com/android/dialer/about/res/layout/license_scrollview.xml new file mode 100644 index 0000000000000000000000000000000000000000..f58bc2f43a52be6ab9210d2075a66e7fc67a73bd --- /dev/null +++ b/java/com/android/dialer/about/res/layout/license_scrollview.xml @@ -0,0 +1,34 @@ + + + + + + + \ No newline at end of file diff --git a/java/com/android/dialer/about/res/raw/keep.xml b/java/com/android/dialer/about/res/raw/keep.xml new file mode 100644 index 0000000000000000000000000000000000000000..e41b8b8d0d45516b1d1fc39bdf9e32c5750e9be2 --- /dev/null +++ b/java/com/android/dialer/about/res/raw/keep.xml @@ -0,0 +1,19 @@ + + + + diff --git a/java/com/android/dialer/about/res/raw/third_party_license_metadata b/java/com/android/dialer/about/res/raw/third_party_license_metadata new file mode 100644 index 0000000000000000000000000000000000000000..1acf3480c2a919d530be4913685dd49780937b57 --- /dev/null +++ b/java/com/android/dialer/about/res/raw/third_party_license_metadata @@ -0,0 +1,34 @@ +40:10695 Android Annotations Support Library +10770:10695 Android Compat Support Library +21501:10695 Android Core UI Support Library +32235:10691 Android Core Utils Support Library +42961:10695 Android Design Support Library +53694:10695 Android Fragments Support Library +64426:10695 Android Graphics Support Library +75162:10691 Android Media Compat Support Library +85892:10691 Android Transition Support Library +96621:10695 Android Compatibility Library v13 +107353:10695 Android Compatibility Library v4 +118085:10695 Android Compatibility Library v7 +128796:16013 Android SDK +144828:11358 Android Common +156196:4771 Glide +160982:11358 Guava JDK5 +172358:12847 jibercsclient +185224:10173 libphonenumber +195416:10699 shortcutbadger +206126:11358 Volley +217495:18982 mime4j +236493:11358 Google Auto +247862:11358 Dagger +259236:11357 Error Prone +270604:11358 J2ObjC +281984:11359 Apache Commons IO +293355:11358 JSR 250 +304725:1602 JSR 305 +306339:11365 JSR 330 +317738:12847 carrierservices +317738:12847 rcsclientlib +330614:11358 material_components +330614:11358 lib +341987:11362 Guava JDK7 diff --git a/java/com/android/dialer/about/res/raw/third_party_licenses b/java/com/android/dialer/about/res/raw/third_party_licenses new file mode 100644 index 0000000000000000000000000000000000000000..c56f8a42c08219e0aa33ef16d0eaf522eb0f955d --- /dev/null +++ b/java/com/android/dialer/about/res/raw/third_party_licenses @@ -0,0 +1,6414 @@ + + +Android Annotations Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Compat Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Core UI Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Core Utils Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +Android Design Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Fragments Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Graphics Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Media Compat Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +Android Transition Support Library: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +Android Compatibility Library v13: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Compatibility Library v4: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android Compatibility Library v7: + + + Copyright (c) 2005-2011, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Android SDK: + +ANDROID SOFTWARE DEVELOPMENT KIT + +Terms and Conditions + +This is the Android Software Development Kit License Agreement. + +1. Introduction + +1.1 The Android Software Development Kit (referred to in this License Agreement as the "SDK" and +specifically including the Android system files, packaged APIs, and Google APIs add-ons) is +licensed to you subject to the terms of this License Agreement. This License Agreement forms a +legally binding contract between you and Google in relation to your use of the SDK. + +1.2 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 +Amphitheatre Parkway, Mountain View, CA 94043, United States. + +2. Accepting this License Agreement + +2.1 In order to use the SDK, you must first agree to this License Agreement. You may not use the +SDK if you do not accept this License Agreement. + +2.2 You can accept this License Agreement by: + +(A) clicking to accept or agree to this License Agreement, where this option is made available to +you; or + +(B) by actually using the SDK. In this case, you agree that use of the SDK constitutes acceptance of +the Licensing Agreement from that point onwards. + +2.3 You may not use the SDK and may not accept the Licensing Agreement if you are a person barred +from receiving the SDK under the laws of the United States or other countries including the country +in which you are resident or from which you use the SDK. + +2.4 If you are agreeing to be bound by this License Agreement on behalf of your employer or other +entity, you represent and warrant that you have full legal authority to bind your employer or such +entity to this License Agreement. If you do not have the requisite authority, you may not accept +the Licensing Agreement or use the SDK on behalf of your employer or other entity. + +3. SDK License from Google + +3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide, +royalty-free, non- assignable and non-exclusive license to use the SDK solely to develop +applications to run on the Android platform. + +3.2 You agree that Google or third parties own all legal right, title and interest in and to the +SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property +Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, +and any and all other proprietary rights. Google reserves all rights not expressly granted to you. + +3.3 Except to the extent required by applicable third party licenses, you may not copy (except for +backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create +derivative works of the SDK or any part of the SDK. Except to the extent required by applicable +third party licenses, you may not load any part of the SDK onto a mobile handset or any other +hardware device except a personal computer, combine any part of the SDK with other software, or +distribute any software or device incorporating a part of the SDK. + +3.4 Use, reproduction and distribution of components of the SDK licensed under an open source +software license are governed solely by the terms of that open source software license and not +this License Agreement. + +3.5 You agree that the form and nature of the SDK that Google provides may change without prior +notice to you and that future versions of the SDK may be incompatible with applications developed +on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) +providing the SDK (or any features within the SDK) to you or to users generally at Google's sole +discretion, without prior notice to you. + +3.6 Nothing in this License Agreement gives you a right to use any of Google's trade names, +trademarks, service marks, logos, domain names, or other distinctive brand features. + +3.7 You agree that you will not remove, obscure, or alter any proprietary rights notices (including +copyright and trademark notices) that may be affixed to or contained within the SDK. + +4. Use of the SDK by You + +4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under +this License Agreement in or to any software applications that you develop using the SDK, including +any intellectual property rights that subsist in those applications. + +4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) this +License Agreement and (b) any applicable law, regulation or generally accepted practices or +guidelines in the relevant jurisdictions (including any laws regarding the export of data or +software to and from the United States or other relevant countries). + +4.3 You agree that if you use the SDK to develop applications for general public users, you will +protect the privacy and legal rights of those users. If the users provide you with user names, +passwords, or other login information or personal information, your must make the users aware that +the information will be available to your application, and you must provide legally adequate privacy +notice and protection for those users. If your application stores personal or sensitive information +provided by users, it must do so securely. If the user provides your application with Google Account +information, your application may only use that information to access the user's Google Account +when, and for the limited purposes for which, the user has given you permission to do so. + +4.4 You agree that you will not engage in any activity with the SDK, including the development or +distribution of an application, that interferes with, disrupts, damages, or accesses in an +unauthorized manner the servers, networks, or other properties or services of any third party +including, but not limited to, Google or any mobile communications carrier. + +4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or +to any third party for) any data, content, or resources that you create, transmit or display through +the Android platform and/or applications for the Android platform, and for the consequences of your +actions (including any loss or damage which Google may suffer) by doing so. + +4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or +to any third party for) any breach of your obligations under this License Agreement, any applicable +third party contract or Terms of Service, or any applicable law or regulation, and for the +consequences (including any loss or damage which Google or any third party may suffer) of any such +breach. + +5. Your Developer Credentials + +5.1 You agree that you are responsible for maintaining the confidentiality of any developer +credentials that may be issued to you by Google or which you may choose yourself and that you will +be solely responsible for all applications that are developed under your developer credentials. + +6. Privacy and Information + +6.1 In order to continually innovate and improve the SDK, Google may collect certain usage +statistics from the software including but not limited to a unique identifier, associated IP +address, version number of the software, and information on which tools and/or services in the SDK +are being used and how they are being used. Before any of this information is collected, the SDK +will notify you and seek your consent. If you withhold consent, the information will not be +collected. + +6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in +accordance with Google's Privacy Policy. + +7. Third Party Applications for the Android Platform + +7.1 If you use the SDK to run applications developed by a third party or that access data, content +or resources provided by a third party, you agree that Google is not responsible for those +applications, data, content, or resources. You understand that all data, content or resources which +you may access through such third party applications are the sole responsibility of the person from +which they originated and that Google is not liable for any loss or damage that you may experience +as a result of the use or access of any of those third party applications, data, content, or +resources. + +7.2 You should be aware the data, content, and resources presented to you through such a third party +application may be protected by intellectual property rights which are owned by the providers (or by +other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute +or create derivative works based on these data, content, or resources (either in whole or in part) +unless you have been specifically given permission to do so by the relevant owners. + +7.3 You acknowledge that your use of such third party applications, data, content, or resources may +be subject to separate terms between you and the relevant third party. In that case, this License +Agreement does not affect your legal relationship with these third parties. + +8. Using Android APIs + +8.1 Google Data APIs + +8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be +protected by intellectual property rights which are owned by Google or those parties that provide +the data (or by other persons or companies on their behalf). Your use of any such API may be subject +to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create +derivative works based on this data (either in whole or in part) unless allowed by the relevant +Terms of Service. + +8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you +shall retrieve data only with the user's explicit consent and only when, and for the limited +purposes for which, the user has given you permission to do so. + +9. Terminating this License Agreement + +9.1 This License Agreement will continue to apply until terminated by either you or Google as set +out below. + +9.2 If you want to terminate this License Agreement, you may do so by ceasing your use of the SDK +and any relevant developer credentials. + +9.3 Google may at any time, terminate this License Agreement with you if: + +(A) you have breached any provision of this License Agreement; or + +(B) Google is required to do so by law; or + +(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated +its relationship with Google or ceased to offer certain parts of the SDK to you; or + +(D) Google decides to no longer providing the SDK or certain parts of the SDK to users in the +country in which you are resident or from which you use the service, or the provision of the SDK or +certain SDK services to you by Google is, in Google's sole discretion, no longer commercially +viable. + +9.4 When this License Agreement comes to an end, all of the legal rights, obligations and +liabilities that you and Google have benefited from, been subject to (or which have accrued over +time whilst this License Agreement has been in force) or which are expressed to continue +indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall +continue to apply to such rights, obligations and liabilities indefinitely. + +10. DISCLAIMER OF WARRANTIES + +10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE +SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE. + +10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE +SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR +COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. + +10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + +11. LIMITATION OF LIABILITY + +11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS +LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY +LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN +AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. + +12. Indemnification + +12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless +Google, its affiliates and their respective directors, officers, employees and agents from and +against any and all claims, actions, suits or proceedings, as well as any and all losses, +liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or +accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any +copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any +person or defames any person or violates their rights of publicity or privacy, and (c) any +non-compliance by you with this License Agreement. + +13. Changes to the License Agreement + +13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. +When these changes are made, Google will make a new version of the License Agreement available on +the website where the SDK is made available. + +14. General Legal Terms + +14.1 This License Agreement constitute the whole legal agreement between you and Google and govern +your use of the SDK (excluding any services which Google may provide to you under a separate written +agreement), and completely replace any prior agreements between you and Google in relation to the +SDK. + +14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is +contained in this License Agreement (or which Google has the benefit of under any applicable law), +this will not be taken to be a formal waiver of Google's rights and that those rights or remedies +will still be available to Google. + +14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision +of this License Agreement is invalid, then that provision will be removed from this License +Agreement without affecting the rest of this License Agreement. The remaining provisions of this +License Agreement will continue to be valid and enforceable. + +14.4 You acknowledge and agree that each member of the group of companies of which Google is the +parent shall be third party beneficiaries to this License Agreement and that such other companies +shall be entitled to directly enforce, and rely upon, any provision of this License Agreement that +confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall +be third party beneficiaries to this License Agreement. + +14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST +COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE +LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE. + +14.6 The rights granted in this License Agreement may not be assigned or transferred by either you +or Google without the prior written approval of the other party. Neither you nor Google shall be +permitted to delegate their responsibilities or obligations under this License Agreement without the +prior written approval of the other party. + +14.7 This License Agreement, and your relationship with Google under this License Agreement, shall +be governed by the laws of the State of California without regard to its conflict of laws +provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located +within the county of Santa Clara, California to resolve any legal matter arising from this License +Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for +injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction. + +April 10, 2009 + + +Android Common: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +Glide: + +Covers library/ + +Copyright 2014 Google, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Google, Inc. + +-------------------------------------------------------------------------- +Covers third_party/gif_decoder + +Copyright (c) 2013 Xcellent Creations, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------- +Covers third_party/disklrucache + +Copyright 2012 Jake Wharton +Copyright 2011 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. +-------------------------------------------------------------------------- +Covers third_party/gif_encoder/AnimatedGifEncoder.java and +third_party/gif_encoder/LZWEncoder.java: + +No copyright asserted on the source code of this class. May be used for any +purpose, however, refer to the Unisys LZW patent for restrictions on use of +the associated LZWEncoder class. Please forward any corrections to +kweiner@fmsware.com. + +----------------------------------------------------------------------------- +Covers third_party/gif_encoder/NeuQuant.java + +Copyright (c) 1994 Anthony Dekker + +NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See +"Kohonen neural networks for optimal colour quantization" in "Network: +Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of +the algorithm. + +Any party obtaining a copy of these files from the author, directly or +indirectly, is granted, free of charge, a full and unrestricted irrevocable, +world-wide, paid up, royalty-free, nonexclusive right and license to deal in +this software and documentation files (the "Software"), including without +limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons who +receive copies from any such party to do so, with the only requirement being +that this copyright notice remain intact. + + +Guava JDK5: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +jibercsclient: + +These components + com.google.android.rcs.core, + com.google.android.rcs.core.utils.CaseInsensitiveMap, + com.google.android.rcs.core.utils.DateTime, + com.google.android.rcs.core.utils.InetAddresses, + com.google.android.rcs.core.network.ConnectivityMonitor, + com.google.android.rcs.client.PrivateDataStorage, + com.google.android.rcs.client.utils.FastXmlSerializer, + com.google.android.rcs.client.utils.XmlUtils, + com.google.android.rcs.client.utils.QueuedWork +are licensed under Apache v2. + +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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +=============================================================================== + +These components + com.google.android.rcs.core.utils.FastBase64, + com.google.android.rcs.core.utils.LibraryLoaderHelper +are licensed under BSD. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +libphonenumber: + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + +shortcutbadger: + +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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + +Volley: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +mime4j: + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + + + THIS PRODUCT ALSO INCLUDES THIRD PARTY SOFTWARE REDISTRIBUTED UNDER THE + FOLLOWING LICENSES: + + Apache Commons Logging, + The Apache Software License, Version 1.1 (commons-logging-1.1.1.jar) + + The Apache Software License, Version 1.1 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by the + Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + + 4. The names "Apache" and "Apache Software Foundation" must + not be used to endorse or promote products derived from this + software without prior written permission. For written + permission, please contact apache@apache.org. + + 5. Products derived from this software may not be called "Apache", + nor may "Apache" appear in their name, without prior written + permission of the Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + + Test messages from the Perl-MIME-Tools project, + + The "Artistic License" + + Preamble + + The intent of this document is to state the conditions under which a + Package may be copied, such that the Copyright Holder maintains some + semblance of artistic control over the development of the package, + while giving the users of the package the right to use and distribute + the Package in a more-or-less customary fashion, plus the right to make + reasonable modifications. + + Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + + 1. You may make and give away verbatim copies of the source form of the + Standard Version of this Package without restriction, provided that you + duplicate all of the original copyright notices and associated disclaimers. + + 2. You may apply bug fixes, portability fixes and other modifications + derived from the Public Domain or from the Copyright Holder. A Package + modified in such a way shall still be considered the Standard Version. + + 3. You may otherwise modify your copy of this Package in any way, provided + that you insert a prominent notice in each changed file stating how and + when you changed that file, and provided that you do at least ONE of the + following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + 4. You may distribute the programs of this Package in object code or + executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + 5. You may charge a reasonable copying fee for any distribution of this + Package. You may charge any fee you choose for support of this + Package. You may not charge a fee for this Package itself. However, + you may distribute this Package in aggregate with other (possibly + commercial) programs as part of a larger (possibly commercial) software + distribution provided that you do not advertise this Package as a + product of your own. You may embed this Package's interpreter within + an executable of yours (by linking); this shall be construed as a mere + form of aggregation, provided that the complete Standard Version of the + interpreter is so embedded. + + 6. The scripts and library files supplied as input to or produced as + output from the programs of this Package do not automatically fall + under the copyright of this Package, but belong to whoever generated + them, and may be sold commercially, and may be aggregated with this + Package. If such scripts or library files are aggregated with this + Package via the so-called "undump" or "unexec" methods of producing a + binary executable image, then distribution of such an image shall + neither be construed as a distribution of this Package nor shall it + fall under the restrictions of Paragraphs 3 and 4, provided that you do + not represent such an executable image as a Standard Version of this + Package. + + 7. C subroutines (or comparably compiled subroutines in other + languages) supplied by you and linked into this Package in order to + emulate subroutines and variables of the language defined by this + Package shall not be considered part of this Package, but are the + equivalent of input as in Paragraph 6, provided these subroutines do + not change the language in any way that would cause it to fail the + regression tests for the language. + + 8. Aggregation of this Package with a commercial distribution is always + permitted provided that the use of this Package is embedded; that is, + when no overt attempt is made to make this Package's interfaces visible + to the end user of the commercial distribution. Such use shall not be + construed as a distribution of this Package. + + 9. The name of the Copyright Holder may not be used to endorse or promote + products derived from this software without specific prior written permission. + + 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + + + + +Google Auto: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +Dagger: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +Error Prone: + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +J2ObjC: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +Apache Commons IO: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + +JSR 250: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +JSR 305: + +Copyright (c) 2007-2009, JSR305 expert group +All rights reserved. + +http://www.opensource.org/licenses/bsd-license.php + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the JSR305 expert group nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +JSR 330: + +JSR-330 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +carrierservices, rcsclientlib: + +These components + com.google.android.rcs.core, + com.google.android.rcs.core.utils.CaseInsensitiveMap, + com.google.android.rcs.core.utils.DateTime, + com.google.android.rcs.core.utils.InetAddresses, + com.google.android.rcs.core.network.ConnectivityMonitor, + com.google.android.rcs.client.PrivateDataStorage, + com.google.android.rcs.client.utils.FastXmlSerializer, + com.google.android.rcs.client.utils.XmlUtils, + com.google.android.rcs.client.utils.QueuedWork +are licensed under Apache v2. + +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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +=============================================================================== + +These components + com.google.android.rcs.core.utils.FastBase64, + com.google.android.rcs.core.utils.LibraryLoaderHelper +are licensed under BSD. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +material_components, lib: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +Guava JDK7: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/java/com/android/dialer/about/res/values-af/strings.xml b/java/com/android/dialer/about/res/values-af/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-af/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-am/strings.xml b/java/com/android/dialer/about/res/values-am/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-am/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ar/strings.xml b/java/com/android/dialer/about/res/values-ar/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ar/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-az/strings.xml b/java/com/android/dialer/about/res/values-az/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-az/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-b+sr+Latn/strings.xml b/java/com/android/dialer/about/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-be/strings.xml b/java/com/android/dialer/about/res/values-be/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-be/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-bg/strings.xml b/java/com/android/dialer/about/res/values-bg/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-bg/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-bn/strings.xml b/java/com/android/dialer/about/res/values-bn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-bn/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-bs/strings.xml b/java/com/android/dialer/about/res/values-bs/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-bs/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ca/strings.xml b/java/com/android/dialer/about/res/values-ca/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ca/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-cs/strings.xml b/java/com/android/dialer/about/res/values-cs/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-cs/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-da/strings.xml b/java/com/android/dialer/about/res/values-da/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-da/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-de/strings.xml b/java/com/android/dialer/about/res/values-de/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-de/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-el/strings.xml b/java/com/android/dialer/about/res/values-el/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-el/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-en-rAU/strings.xml b/java/com/android/dialer/about/res/values-en-rAU/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-en-rAU/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-en-rGB/strings.xml b/java/com/android/dialer/about/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-en-rGB/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-en-rIN/strings.xml b/java/com/android/dialer/about/res/values-en-rIN/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-en-rIN/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-es-rUS/strings.xml b/java/com/android/dialer/about/res/values-es-rUS/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-es-rUS/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-es/strings.xml b/java/com/android/dialer/about/res/values-es/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-es/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-et/strings.xml b/java/com/android/dialer/about/res/values-et/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-et/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-eu/strings.xml b/java/com/android/dialer/about/res/values-eu/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-eu/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-fa/strings.xml b/java/com/android/dialer/about/res/values-fa/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-fa/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-fi/strings.xml b/java/com/android/dialer/about/res/values-fi/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-fi/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-fr-rCA/strings.xml b/java/com/android/dialer/about/res/values-fr-rCA/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-fr-rCA/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-fr/strings.xml b/java/com/android/dialer/about/res/values-fr/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-fr/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-gl/strings.xml b/java/com/android/dialer/about/res/values-gl/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-gl/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-gu/strings.xml b/java/com/android/dialer/about/res/values-gu/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-gu/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-hi/strings.xml b/java/com/android/dialer/about/res/values-hi/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-hi/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-hr/strings.xml b/java/com/android/dialer/about/res/values-hr/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-hr/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-hu/strings.xml b/java/com/android/dialer/about/res/values-hu/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-hu/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-hy/strings.xml b/java/com/android/dialer/about/res/values-hy/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-hy/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-in/strings.xml b/java/com/android/dialer/about/res/values-in/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-in/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-is/strings.xml b/java/com/android/dialer/about/res/values-is/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-is/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-it/strings.xml b/java/com/android/dialer/about/res/values-it/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-it/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-iw/strings.xml b/java/com/android/dialer/about/res/values-iw/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-iw/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ja/strings.xml b/java/com/android/dialer/about/res/values-ja/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ja/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ka/strings.xml b/java/com/android/dialer/about/res/values-ka/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ka/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-kk/strings.xml b/java/com/android/dialer/about/res/values-kk/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-kk/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-km/strings.xml b/java/com/android/dialer/about/res/values-km/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-km/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-kn/strings.xml b/java/com/android/dialer/about/res/values-kn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-kn/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ko/strings.xml b/java/com/android/dialer/about/res/values-ko/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ko/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ky/strings.xml b/java/com/android/dialer/about/res/values-ky/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ky/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-lo/strings.xml b/java/com/android/dialer/about/res/values-lo/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-lo/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-lt/strings.xml b/java/com/android/dialer/about/res/values-lt/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-lt/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-lv/strings.xml b/java/com/android/dialer/about/res/values-lv/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-lv/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-mk/strings.xml b/java/com/android/dialer/about/res/values-mk/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-mk/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ml/strings.xml b/java/com/android/dialer/about/res/values-ml/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ml/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-mn/strings.xml b/java/com/android/dialer/about/res/values-mn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-mn/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-mr/strings.xml b/java/com/android/dialer/about/res/values-mr/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-mr/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ms/strings.xml b/java/com/android/dialer/about/res/values-ms/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ms/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-my/strings.xml b/java/com/android/dialer/about/res/values-my/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-my/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-nb/strings.xml b/java/com/android/dialer/about/res/values-nb/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-nb/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ne/strings.xml b/java/com/android/dialer/about/res/values-ne/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ne/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-nl/strings.xml b/java/com/android/dialer/about/res/values-nl/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-nl/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-no/strings.xml b/java/com/android/dialer/about/res/values-no/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-no/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-pa/strings.xml b/java/com/android/dialer/about/res/values-pa/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-pa/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-pl/strings.xml b/java/com/android/dialer/about/res/values-pl/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-pl/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-pt-rBR/strings.xml b/java/com/android/dialer/about/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-pt-rBR/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-pt-rPT/strings.xml b/java/com/android/dialer/about/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-pt-rPT/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-pt/strings.xml b/java/com/android/dialer/about/res/values-pt/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-pt/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ro/strings.xml b/java/com/android/dialer/about/res/values-ro/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ro/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ru/strings.xml b/java/com/android/dialer/about/res/values-ru/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ru/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-si/strings.xml b/java/com/android/dialer/about/res/values-si/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-si/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-sk/strings.xml b/java/com/android/dialer/about/res/values-sk/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-sk/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-sl/strings.xml b/java/com/android/dialer/about/res/values-sl/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-sl/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-sq/strings.xml b/java/com/android/dialer/about/res/values-sq/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-sq/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-sr/strings.xml b/java/com/android/dialer/about/res/values-sr/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-sr/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-sv/strings.xml b/java/com/android/dialer/about/res/values-sv/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-sv/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-sw/strings.xml b/java/com/android/dialer/about/res/values-sw/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-sw/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ta/strings.xml b/java/com/android/dialer/about/res/values-ta/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ta/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-te/strings.xml b/java/com/android/dialer/about/res/values-te/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-te/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-th/strings.xml b/java/com/android/dialer/about/res/values-th/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-th/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-tl/strings.xml b/java/com/android/dialer/about/res/values-tl/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-tl/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-tr/strings.xml b/java/com/android/dialer/about/res/values-tr/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-tr/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-uk/strings.xml b/java/com/android/dialer/about/res/values-uk/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-uk/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-ur/strings.xml b/java/com/android/dialer/about/res/values-ur/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-ur/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-uz/strings.xml b/java/com/android/dialer/about/res/values-uz/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-uz/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-vi/strings.xml b/java/com/android/dialer/about/res/values-vi/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-vi/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-zh-rCN/strings.xml b/java/com/android/dialer/about/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-zh-rCN/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-zh-rHK/strings.xml b/java/com/android/dialer/about/res/values-zh-rHK/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-zh-rHK/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-zh-rTW/strings.xml b/java/com/android/dialer/about/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-zh-rTW/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values-zu/strings.xml b/java/com/android/dialer/about/res/values-zu/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec60d0e6bbd54c47ce6b23c1d948736817c7007f --- /dev/null +++ b/java/com/android/dialer/about/res/values-zu/strings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/java/com/android/dialer/about/res/values/strings.xml b/java/com/android/dialer/about/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..be7697cf2699cb7b34ea83fec893f284eddb06b5 --- /dev/null +++ b/java/com/android/dialer/about/res/values/strings.xml @@ -0,0 +1,39 @@ + + + + build_version + + + Build version + + + open_source_licenses + + + License details for open source software + + + Open source licenses + + + privacy_policy + + + Privacy policy + + + http://www.google.com/policies/privacy + + + Terms of service + + + terms_of_service + + + http://www.google.com/policies/terms + + diff --git a/java/com/android/dialer/about/res/xml/about_phone_fragment.xml b/java/com/android/dialer/about/res/xml/about_phone_fragment.xml new file mode 100644 index 0000000000000000000000000000000000000000..51f1d3eb045e28f9959b1d2022c203dfb027b98d --- /dev/null +++ b/java/com/android/dialer/about/res/xml/about_phone_fragment.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/java/com/android/dialer/app/AndroidManifest.xml b/java/com/android/dialer/app/AndroidManifest.xml index 67290b5915f810a1b981a597565d181f5dc89a64..de4b48c515e8dcdc268bf97bcc1980ccd6f8c997 100644 --- a/java/com/android/dialer/app/AndroidManifest.xml +++ b/java/com/android/dialer/app/AndroidManifest.xml @@ -55,7 +55,7 @@ + android:targetSdkVersion="26"/> @@ -109,6 +109,16 @@ + + + + + + + + + paused -> resumed, so it // will not cause an extra view to be sent out on rotation @@ -522,33 +517,39 @@ public class DialtactsActivity extends TransactionSafeActivity } mFloatingActionButtonController.align(getFabAlignment(), false /* animate */); - if (Calls.CONTENT_TYPE.equals(getIntent().getType())) { - // Externally specified extras take precedence to EXTRA_SHOW_TAB, which is only - // used internally. - final Bundle extras = getIntent().getExtras(); - if (extras != null && extras.getInt(Calls.EXTRA_CALL_TYPE_FILTER) == Calls.VOICEMAIL_TYPE) { - mListsFragment.showTab(DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); - Logger.get(this).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CLICKED); - } else { - mListsFragment.showTab(DialtactsPagerAdapter.TAB_INDEX_HISTORY); + if (mFirstLaunch) { + // Only process the Intent the first time onResume() is called after receiving it + if (Calls.CONTENT_TYPE.equals(getIntent().getType())) { + // Externally specified extras take precedence to EXTRA_SHOW_TAB, which is only + // used internally. + final Bundle extras = getIntent().getExtras(); + if (extras != null && extras.getInt(Calls.EXTRA_CALL_TYPE_FILTER) == Calls.VOICEMAIL_TYPE) { + mListsFragment.showTab(DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); + Logger.get(this).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CLICKED); + } else { + mListsFragment.showTab(DialtactsPagerAdapter.TAB_INDEX_HISTORY); + } + } else if (getIntent().hasExtra(EXTRA_SHOW_TAB)) { + int index = + getIntent().getIntExtra(EXTRA_SHOW_TAB, DialtactsPagerAdapter.TAB_INDEX_SPEED_DIAL); + if (index < mListsFragment.getTabCount()) { + // Hide dialpad since this is an explicit intent to show a specific tab, which is coming + // from missed call or voicemail notification. + hideDialpadFragment(false, false); + exitSearchUi(); + mListsFragment.showTab(index); + } } - } else if (getIntent().hasExtra(EXTRA_SHOW_TAB)) { - int index = - getIntent().getIntExtra(EXTRA_SHOW_TAB, DialtactsPagerAdapter.TAB_INDEX_SPEED_DIAL); - if (index < mListsFragment.getTabCount()) { - // Hide dialpad since this is an explicit intent to show a specific tab, which is coming - // from missed call or voicemail notification. - hideDialpadFragment(false, false); - exitSearchUi(); - mListsFragment.showTab(index); + + if (getIntent().getBooleanExtra(EXTRA_CLEAR_NEW_VOICEMAILS, false)) { + CallLogNotificationsService.markNewVoicemailsAsOld(this, null); } } - if (getIntent().getBooleanExtra(EXTRA_CLEAR_NEW_VOICEMAILS, false)) { - CallLogNotificationsService.markNewVoicemailsAsOld(this, null); - } + mFirstLaunch = false; setSearchBoxHint(); + timeTabSelected = SystemClock.elapsedRealtime(); mP13nLogger.reset(); mP13nRanker.refresh( @@ -586,7 +587,10 @@ public class DialtactsActivity extends TransactionSafeActivity SystemClock.elapsedRealtime() - timeTabSelected >= HISTORY_TAB_SEEN_TIMEOUT; boolean isOnHistoryTab = mListsFragment.getCurrentTabIndex() == DialtactsPagerAdapter.TAB_INDEX_HISTORY; - if (isOnHistoryTab && timeoutElapsed && !isChangingConfigurations()) { + if (isOnHistoryTab + && timeoutElapsed + && !isChangingConfigurations() + && !getSystemService(KeyguardManager.class).isKeyguardLocked()) { mListsFragment.markMissedCallsAsReadAndRemoveNotifications(); } } @@ -857,7 +861,10 @@ public class DialtactsActivity extends TransactionSafeActivity /** Finishes hiding the dialpad fragment after any animations are completed. */ private void commitDialpadFragmentHide() { - if (!mStateSaved && mDialpadFragment != null && !mDialpadFragment.isHidden()) { + if (!mStateSaved + && mDialpadFragment != null + && !mDialpadFragment.isHidden() + && !isDestroyed()) { final FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.hide(mDialpadFragment); ft.commit(); @@ -1006,6 +1013,7 @@ public class DialtactsActivity extends TransactionSafeActivity @Override public void onNewIntent(Intent newIntent) { setIntent(newIntent); + mFirstLaunch = true; mStateSaved = false; displayFragment(newIntent); @@ -1480,7 +1488,7 @@ public class DialtactsActivity extends TransactionSafeActivity Menu menu = getMenu(); MenuItem clearFrequents = menu.findItem(R.id.menu_clear_frequents); clearFrequents.setVisible( - PermissionsUtil.hasContactsPermissions(DialtactsActivity.this) + PermissionsUtil.hasContactsReadPermissions(DialtactsActivity.this) && mListsFragment != null && mListsFragment.hasFrequents()); diff --git a/java/com/android/dialer/app/calllog/BlockReportSpamListener.java b/java/com/android/dialer/app/calllog/BlockReportSpamListener.java index 66f40bcd72bab3a9e199328cafe0072b8f8a332c..28082df2bb8dc07d130b5a759df45ea2e2ac07cf 100644 --- a/java/com/android/dialer/app/calllog/BlockReportSpamListener.java +++ b/java/com/android/dialer/app/calllog/BlockReportSpamListener.java @@ -20,13 +20,15 @@ import android.app.FragmentManager; import android.content.ContentValues; import android.content.Context; import android.net.Uri; +import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import com.android.dialer.blocking.BlockReportSpamDialogs; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.ContactSource; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; -import com.android.dialer.logging.nano.ReportingLocation; +import com.android.dialer.logging.ReportingLocation; import com.android.dialer.spam.Spam; /** Listener to show dialogs for block and report spam actions. */ @@ -54,7 +56,7 @@ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClic final String number, final String countryIso, final int callType, - final int contactSourceType) { + @NonNull final ContactSource.Type contactSourceType) { BlockReportSpamDialogs.BlockReportSpamDialogFragment.newInstance( displayNumber, Spam.get(mContext).isDialogReportSpamCheckedByDefault(), @@ -98,7 +100,7 @@ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClic final String number, final String countryIso, final int callType, - final int contactSourceType) { + @NonNull final ContactSource.Type contactSourceType) { BlockReportSpamDialogs.BlockDialogFragment.newInstance( displayNumber, Spam.get(mContext).isSpamEnabled(), @@ -142,7 +144,7 @@ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClic final String number, final String countryIso, final int callType, - final int contactSourceType, + final ContactSource.Type contactSourceType, final boolean isSpam, final Integer blockId) { BlockReportSpamDialogs.UnblockDialogFragment.newInstance( @@ -185,7 +187,7 @@ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClic final String number, final String countryIso, final int callType, - final int contactSourceType) { + final ContactSource.Type contactSourceType) { BlockReportSpamDialogs.ReportNotSpamDialogFragment.newInstance( displayNumber, new BlockReportSpamDialogs.OnConfirmListener() { diff --git a/java/com/android/dialer/app/calllog/CallLogActivity.java b/java/com/android/dialer/app/calllog/CallLogActivity.java index 719ab4369563bbb258ef5dd4cca25d8478af2658..443171d3f677f1745b0815585bcf2d7176d68864 100644 --- a/java/com/android/dialer/app/calllog/CallLogActivity.java +++ b/java/com/android/dialer/app/calllog/CallLogActivity.java @@ -33,7 +33,7 @@ import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.ScreenEvent; +import com.android.dialer.logging.ScreenEvent; import com.android.dialer.util.TransactionSafeActivity; import com.android.dialer.util.ViewUtil; diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index 06f48aa207811f95a8a858ea4312738c9ac7ab2a..2f8a58c8aa9ee2114861082f4c700f69aaea2520 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -18,6 +18,7 @@ package com.android.dialer.app.calllog; import android.app.Activity; import android.content.ContentUris; +import android.content.DialogInterface; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; @@ -33,13 +34,14 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.SparseBooleanArray; +import android.util.SparseArray; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; @@ -59,8 +61,8 @@ import com.android.dialer.app.contactinfo.ContactInfoCache; import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter; import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter.OnVoicemailDeletedListener; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; -import com.android.dialer.calldetails.nano.CallDetailsEntries; -import com.android.dialer.calldetails.nano.CallDetailsEntries.CallDetailsEntry; +import com.android.dialer.calldetails.CallDetailsEntries; +import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; import com.android.dialer.calllogutils.PhoneAccountUtils; import com.android.dialer.calllogutils.PhoneCallDetails; import com.android.dialer.common.Assert; @@ -71,12 +73,13 @@ import com.android.dialer.common.concurrent.AsyncTaskExecutors; import com.android.dialer.enrichedcall.EnrichedCallCapabilities; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager; -import com.android.dialer.enrichedcall.historyquery.proto.nano.HistoryResult; +import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult; import com.android.dialer.lightbringer.Lightbringer; import com.android.dialer.lightbringer.LightbringerComponent; import com.android.dialer.lightbringer.LightbringerListener; +import com.android.dialer.logging.ContactSource; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; import com.android.dialer.phonenumbercache.CallLogQuery; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; @@ -105,6 +108,9 @@ public class CallLogAdapter extends GroupingListAdapter public static final String LOAD_DATA_TASK_IDENTIFIER = "load_data"; + public static final String ENABLE_CALL_LOG_MULTI_SELECT = "enable_call_log_multiselect"; + public static final boolean ENABLE_CALL_LOG_MULTI_SELECT_FLAG = false; + protected final Activity mActivity; protected final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; /** Cache for repeated requests to Telecom/Telephony. */ @@ -129,8 +135,8 @@ public class CallLogAdapter extends GroupingListAdapter private final CallLogAlertManager mCallLogAlertManager; - public static ActionMode mActionMode = null; - private final SparseBooleanArray selectedItems = new SparseBooleanArray(); + public ActionMode mActionMode = null; + private final SparseArray selectedItems = new SparseArray<>(); private final ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { @@ -155,7 +161,15 @@ public class CallLogAdapter extends GroupingListAdapter // Called when the user selects a contextual menu item @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - return false; + if (item.getItemId() == R.id.action_bar_delete_menu_item) { + if (selectedItems.size() > 0) { + showDeleteSelectedItemsDialog(); + } + mode.finish(); + return true; + } else { + return false; + } } // Called when the user exits the action mode @@ -167,14 +181,68 @@ public class CallLogAdapter extends GroupingListAdapter } }; + // Todo (uabdullah): Use plurals http://b/37751831 + private void showDeleteSelectedItemsDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); + Assert.checkArgument(selectedItems.size() > 0); + String voicemailString = + selectedItems.size() == 1 + ? mActivity.getResources().getString(R.string.voicemailMultiSelectVoicemail) + : mActivity.getResources().getString(R.string.voicemailMultiSelectVoicemails); + String deleteVoicemailTitle = + mActivity + .getResources() + .getString(R.string.voicemailMultiSelectDialogTitle, voicemailString); + SparseArray voicemailsToDeleteOnConfirmation = selectedItems.clone(); + builder.setTitle(deleteVoicemailTitle); + + builder.setPositiveButton( + mActivity.getResources().getString(R.string.voicemailMultiSelectDeleteConfirm), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + deleteSelectedItems(voicemailsToDeleteOnConfirmation); + dialog.cancel(); + } + }); + + builder.setNegativeButton( + mActivity.getResources().getString(R.string.voicemailMultiSelectDeleteCancel), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + + private void deleteSelectedItems(SparseArray voicemailsToDelete) { + for (int i = 0; i < voicemailsToDelete.size(); i++) { + String voicemailUri = voicemailsToDelete.get(voicemailsToDelete.keyAt(i)); + CallLogAsyncTaskUtil.deleteVoicemail(mActivity, Uri.parse(voicemailUri), null); + } + } + private final View.OnLongClickListener mLongPressListener = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (ConfigProviderBindings.get(v.getContext()) - .getBoolean("enable_call_log_multiselect", false)) { - v.startActionMode(mActionModeCallback); - return false; + .getBoolean(ENABLE_CALL_LOG_MULTI_SELECT, ENABLE_CALL_LOG_MULTI_SELECT_FLAG) + && mVoicemailPlaybackPresenter != null) { + if (v.getId() == R.id.primary_action_view || v.getId() == R.id.quick_contact_photo) { + if (mActionMode == null) { + mActionMode = v.startActionMode(mActionModeCallback); + } + CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) v.getTag(); + viewHolder.quickContactView.setVisibility(View.GONE); + viewHolder.checkBoxView.setVisibility(View.VISIBLE); + mExpandCollapseListener.onClick(v); + return true; + } } return true; } @@ -190,15 +258,20 @@ public class CallLogAdapter extends GroupingListAdapter return; } if (mActionMode != null && viewHolder.voicemailUri != null) { - if (selectedItems.get((int) ContentUris.parseId(Uri.parse(viewHolder.voicemailUri)))) { - selectedItems.delete((int) ContentUris.parseId(Uri.parse(viewHolder.voicemailUri))); + int id = getVoicemailId(viewHolder.voicemailUri); + if (selectedItems.get(id) != null) { + selectedItems.delete(id); viewHolder.checkBoxView.setVisibility(View.GONE); viewHolder.quickContactView.setVisibility(View.VISIBLE); } else { viewHolder.quickContactView.setVisibility(View.GONE); viewHolder.checkBoxView.setVisibility(View.VISIBLE); - selectedItems.put( - (int) ContentUris.parseId(Uri.parse(viewHolder.voicemailUri)), true); + selectedItems.put(getVoicemailId(viewHolder.voicemailUri), viewHolder.voicemailUri); + } + + if (selectedItems.size() == 0) { + mActionMode.finish(); + return; } mActionMode.setTitle(Integer.toString(selectedItems.size())); return; @@ -216,12 +289,10 @@ public class CallLogAdapter extends GroupingListAdapter getEnrichedCallManager().getCapabilities(viewHolder.number); viewHolder.isCallComposerCapable = capabilities != null && capabilities.supportsCallComposer(); - - CallDetailsEntries callDetailsEntries = viewHolder.getDetailedPhoneDetails(); - setCallDetailsEntriesHistoryResults( + generateAndMapNewCallDetailsEntriesHistoryResults( viewHolder.number, - callDetailsEntries, - getAllHistoricalData(viewHolder.number, callDetailsEntries)); + viewHolder.getDetailedPhoneDetails(), + getAllHistoricalData(viewHolder.number, viewHolder.getDetailedPhoneDetails())); if (viewHolder.rowId == mCurrentlyExpandedRowId) { // Hide actions, if the clicked item is the expanded item. @@ -241,6 +312,12 @@ public class CallLogAdapter extends GroupingListAdapter } }; + private static int getVoicemailId(String voicemailUri) { + Assert.checkArgument(voicemailUri != null); + Assert.checkArgument(voicemailUri.length() > 0); + return (int) ContentUris.parseId(Uri.parse(voicemailUri)); + } + /** * A list of {@link CallLogQuery#ID} that will be hidden. The hide might be temporary so instead * if removing an item, it will be shown as an invisible view. This simplifies the calculation of @@ -299,7 +376,7 @@ public class CallLogAdapter extends GroupingListAdapter mContactInfoCache = contactInfoCache; - if (!PermissionsUtil.hasContactsPermissions(activity)) { + if (!PermissionsUtil.hasContactsReadPermissions(activity)) { mContactInfoCache.disableRequestProcessing(); } @@ -451,6 +528,7 @@ public class CallLogAdapter extends GroupingListAdapter viewHolder.callLogEntryView.setTag(viewHolder); viewHolder.primaryActionView.setTag(viewHolder); + viewHolder.quickContactView.setTag(viewHolder); return viewHolder; } @@ -547,16 +625,19 @@ public class CallLogAdapter extends GroupingListAdapter // the value will be false while capabilities are requested. mExpandCollapseListener will // attempt to set the field properly in that case views.isCallComposerCapable = isCallComposerCapable(views.number); - setCallDetailsEntriesHistoryResults( - views.number, callDetailsEntries, getAllHistoricalData(views.number, callDetailsEntries)); - views.setDetailedPhoneDetails(callDetailsEntries); + CallDetailsEntries updatedCallDetailsEntries = + generateAndMapNewCallDetailsEntriesHistoryResults( + views.number, + callDetailsEntries, + getAllHistoricalData(views.number, callDetailsEntries)); + views.setDetailedPhoneDetails(updatedCallDetailsEntries); views.lightbringerReady = getLightbringer().isReachable(mActivity, views.number); final AsyncTask loadDataTask = new AsyncTask() { @Override protected Boolean doInBackground(Void... params) { views.blockId = - mFilteredNumberAsyncQueryHandler.getBlockedIdSynchronousForCalllogOnly( + mFilteredNumberAsyncQueryHandler.getBlockedIdSynchronous( views.number, views.countryIso); details.isBlocked = views.blockId != null; if (isCancelled()) { @@ -625,23 +706,27 @@ public class CallLogAdapter extends GroupingListAdapter return historicalData; } - private void setCallDetailsEntriesHistoryResults( + private static CallDetailsEntries generateAndMapNewCallDetailsEntriesHistoryResults( @Nullable String number, @NonNull CallDetailsEntries callDetailsEntries, @NonNull Map> mappedResults) { if (number == null) { - return; + return callDetailsEntries; } - for (CallDetailsEntry entry : callDetailsEntries.entries) { + CallDetailsEntries.Builder mutableCallDetailsEntries = CallDetailsEntries.newBuilder(); + for (CallDetailsEntry entry : callDetailsEntries.getEntriesList()) { + CallDetailsEntry.Builder newEntry = CallDetailsEntry.newBuilder().mergeFrom(entry); List results = mappedResults.get(entry); if (results != null) { - entry.historyResults = mappedResults.get(entry).toArray(new HistoryResult[0]); + newEntry.addAllHistoryResults(mappedResults.get(entry)); LogUtil.v( - "CallLogAdapter.setCallDetailsEntriesHistoryResults", + "CallLogAdapter.generateAndMapNewCallDetailsEntriesHistoryResults", "mapped %d results", - entry.historyResults.length); + newEntry.getHistoryResultsList().size()); } + mutableCallDetailsEntries.addEntries(newEntry.build()); } + return mutableCallDetailsEntries.build(); } /** @@ -703,21 +788,21 @@ public class CallLogAdapter extends GroupingListAdapter private static CallDetailsEntries createCallDetailsEntries(Cursor cursor, int count) { Assert.isMainThread(); int position = cursor.getPosition(); - CallDetailsEntries entries = new CallDetailsEntries(); - entries.entries = new CallDetailsEntry[count]; + CallDetailsEntries.Builder entries = CallDetailsEntries.newBuilder(); for (int i = 0; i < count; i++) { - CallDetailsEntry entry = new CallDetailsEntry(); - entry.callId = cursor.getLong(CallLogQuery.ID); - entry.callType = cursor.getInt(CallLogQuery.CALL_TYPE); - entry.dataUsage = cursor.getLong(CallLogQuery.DATA_USAGE); - entry.date = cursor.getLong(CallLogQuery.DATE); - entry.duration = cursor.getLong(CallLogQuery.DURATION); - entry.features |= cursor.getInt(CallLogQuery.FEATURES); - entries.entries[i] = entry; + CallDetailsEntry.Builder entry = + CallDetailsEntry.newBuilder() + .setCallId(cursor.getLong(CallLogQuery.ID)) + .setCallType(cursor.getInt(CallLogQuery.CALL_TYPE)) + .setDataUsage(cursor.getLong(CallLogQuery.DATA_USAGE)) + .setDate(cursor.getLong(CallLogQuery.DATE)) + .setDuration(cursor.getLong(CallLogQuery.DURATION)) + .setFeatures(cursor.getInt(CallLogQuery.FEATURES)); + entries.addEntries(entry.build()); cursor.moveToNext(); } cursor.moveToPosition(position); - return entries; + return entries.build(); } /** @@ -794,14 +879,25 @@ public class CallLogAdapter extends GroupingListAdapter } views.info = info; - views.numberType = - (String) - Phone.getTypeLabel(mActivity.getResources(), details.numberType, details.numberLabel); + views.numberType = getNumberType(mActivity.getResources(), details); mCallLogListItemHelper.updatePhoneCallDetails(details); return true; } + private static String getNumberType(Resources res, PhoneCallDetails details) { + // Label doesn't make much sense if the information is coming from CNAP or Cequint Caller ID. + if (details.sourceType == ContactSource.Type.SOURCE_TYPE_CNAP + || details.sourceType == ContactSource.Type.SOURCE_TYPE_CEQUINT_CALLER_ID) { + return ""; + } + // Returns empty label instead of "custom" if the custom label is empty. + if (details.numberType == Phone.TYPE_CUSTOM && TextUtils.isEmpty(details.numberLabel)) { + return ""; + } + return (String) Phone.getTypeLabel(res, details.numberType, details.numberLabel); + } + /** * Render item view given position. This is running on UI thread so DO NOT put any expensive * operation into it. @@ -822,7 +918,7 @@ public class CallLogAdapter extends GroupingListAdapter details.contactUserType == ContactsUtils.USER_TYPE_WORK ? View.VISIBLE : View.GONE); if (views.voicemailUri != null - && selectedItems.get((int) ContentUris.parseId(Uri.parse(views.voicemailUri)))) { + && selectedItems.get(getVoicemailId(views.voicemailUri)) != null) { views.checkBoxView.setVisibility(View.VISIBLE); views.quickContactView.setVisibility(View.GONE); } else if (views.voicemailUri != null) { diff --git a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java index 2aedb6f17ab3651d3864bfd262b282539dfe7545..a58357448327f7ffa9bf7946cf43d7b8c5c46b1b 100644 --- a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java +++ b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java @@ -83,12 +83,7 @@ public class CallLogAsyncTaskUtil { new AsyncTask() { @Override public Void doInBackground(Void... params) { - ContentValues values = new ContentValues(); - values.put(Voicemails.DELETED, "1"); - context.getContentResolver().update(voicemailUri, values, null, null); - // TODO(b/35440541): check which source package is changed. Don't need - // to upload changes on foreign voicemails, they will get a PROVIDER_CHANGED - uploadVoicemailLocalChangesToServer(context); + deleteVoicemailSynchronous(context, voicemailUri); return null; } @@ -101,6 +96,15 @@ public class CallLogAsyncTaskUtil { }); } + public static void deleteVoicemailSynchronous(Context context, Uri voicemailUri) { + ContentValues values = new ContentValues(); + values.put(Voicemails.DELETED, "1"); + context.getContentResolver().update(voicemailUri, values, null, null); + // TODO(b/35440541): check which source package is changed. Don't need + // to upload changes on foreign voicemails, they will get a PROVIDER_CHANGED + uploadVoicemailLocalChangesToServer(context); + } + public static void markCallAsRead(@NonNull final Context context, @NonNull final long[] callIds) { if (!PermissionsUtil.hasPhonePermissions(context)) { return; diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java index fcc34ebefb2c15dd0d4549078c124778cf552723..6e4b23fc1ec6e1214149cbf665d1c76d1c564076 100644 --- a/java/com/android/dialer/app/calllog/CallLogFragment.java +++ b/java/com/android/dialer/app/calllog/CallLogFragment.java @@ -41,7 +41,6 @@ import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.android.contacts.common.GeoUtil; import com.android.dialer.app.Bindings; import com.android.dialer.app.R; import com.android.dialer.app.calllog.calllogcache.CallLogCache; @@ -56,6 +55,7 @@ import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.database.CallLogQueryHandler; +import com.android.dialer.location.GeoUtil; import com.android.dialer.phonenumbercache.ContactInfoHelper; import com.android.dialer.util.PermissionsUtil; @@ -200,9 +200,18 @@ public class CallLogFragment extends Fragment final ContentResolver resolver = activity.getContentResolver(); mCallLogQueryHandler = new CallLogQueryHandler(activity, resolver, this, mLogLimit); mKeyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE); - resolver.registerContentObserver(CallLog.CONTENT_URI, true, mCallLogObserver); - resolver.registerContentObserver( - ContactsContract.Contacts.CONTENT_URI, true, mContactsObserver); + + if (PermissionsUtil.hasCallLogReadPermissions(getContext())) { + resolver.registerContentObserver(CallLog.CONTENT_URI, true, mCallLogObserver); + } else { + LogUtil.w("CallLogFragment.onCreate", "call log permission not available"); + } + if (PermissionsUtil.hasContactsReadPermissions(getContext())) { + resolver.registerContentObserver( + ContactsContract.Contacts.CONTENT_URI, true, mContactsObserver); + } else { + LogUtil.w("CallLogFragment.onCreate", "contacts permission not available."); + } setHasOptionsMenu(true); } @@ -376,6 +385,7 @@ public class CallLogFragment extends Fragment super.onStop(); mAdapter.onStop(); + mContactInfoCache.stop(); } @Override @@ -398,8 +408,6 @@ public class CallLogFragment extends Fragment outState.putBoolean(KEY_HAS_READ_CALL_LOG_PERMISSION, mHasReadCallLogPermission); outState.putBoolean(KEY_REFRESH_DATA_REQUIRED, mRefreshDataRequired); - mContactInfoCache.stop(); - mAdapter.onSaveInstanceState(outState); } @@ -495,7 +503,7 @@ public class CallLogFragment extends Fragment if (mKeyguardManager != null && !mKeyguardManager.inKeyguardRestrictedInputMode() && mCallTypeFilter == Calls.VOICEMAIL_TYPE) { - CallLogNotificationsQueryHelper.updateVoicemailNotifications(getActivity()); + CallLogNotificationsService.markNewVoicemailsAsOld(getActivity(), null); } } diff --git a/java/com/android/dialer/app/calllog/CallLogListItemHelper.java b/java/com/android/dialer/app/calllog/CallLogListItemHelper.java index a5df8cca17328803175e59c219f358939b5d1a70..ac43b9ea749bee66ef3ed6d7ab6217c401a6e866 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemHelper.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemHelper.java @@ -269,7 +269,7 @@ import com.android.dialer.compat.AppCompatConstants; if (!TextUtils.isEmpty(details.getPreferredName())) { recipient = details.getPreferredName(); } else { - recipient = details.displayNumber + details.postDialDigits; + recipient = details.displayNumber; } return recipient; } diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java index 9adcddb3ce8638b5dbe96d794d9f9940c17e6bde..1daccd1a41ed5bb59730dd918853f9f636fb39d8 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java @@ -22,16 +22,21 @@ import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.AsyncTask; +import android.provider.CallLog; import android.provider.CallLog.Calls; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.PhoneNumberUtils; +import android.text.BidiFormatter; +import android.text.TextDirectionHeuristics; import android.text.TextUtils; +import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; import android.view.ViewStub; @@ -41,7 +46,7 @@ import android.widget.QuickContactBadge; import android.widget.TextView; import com.android.contacts.common.ClipboardUtils; import com.android.contacts.common.ContactPhotoManager; -import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; +import com.android.contacts.common.compat.PhoneNumberUtilsCompat; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.contacts.common.util.UriUtils; import com.android.dialer.app.DialtactsActivity; @@ -53,14 +58,17 @@ import com.android.dialer.blocking.BlockedNumbersMigrator; import com.android.dialer.blocking.FilteredNumberCompat; import com.android.dialer.blocking.FilteredNumbersUtil; import com.android.dialer.callcomposer.CallComposerActivity; -import com.android.dialer.callcomposer.nano.CallComposerContact; -import com.android.dialer.calldetails.nano.CallDetailsEntries; +import com.android.dialer.callcomposer.CallComposerContact; +import com.android.dialer.calldetails.CallDetailsEntries; +import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; import com.android.dialer.compat.CompatUtils; import com.android.dialer.lightbringer.Lightbringer; import com.android.dialer.lightbringer.LightbringerComponent; +import com.android.dialer.logging.ContactSource; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.ScreenEvent; import com.android.dialer.phonenumbercache.CachedNumberLookupService; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.PhoneNumberCache; @@ -76,7 +84,9 @@ import com.android.dialer.util.DialerUtils; * CallLogAdapter. */ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder - implements View.OnClickListener, MenuItem.OnMenuItemClickListener { + implements View.OnClickListener, + MenuItem.OnMenuItemClickListener, + View.OnCreateContextMenuListener { /** The root view of the call log list item */ public final View rootView; /** The quick contact badge for the contact. */ @@ -98,7 +108,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private final CachedNumberLookupService mCachedNumberLookupService; private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; private final OnClickListener mBlockReportListener; - private final int mPhotoSize; /** Whether the data fields are populated by the worker thread, ready to be shown. */ public boolean isLoaded; /** The view containing call log item actions. Null until the ViewStub is inflated. */ @@ -175,7 +184,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder * The name or number associated with the call. Cached here for use when setting content * descriptions on buttons in the actions ViewStub when it is inflated. */ - public CharSequence nameOrNumber; + @Nullable public CharSequence nameOrNumber; /** * The call type or Location associated with the call. Cached here for use when setting text for a * voicemail log's call button @@ -237,7 +246,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder this.primaryActionButtonView = primaryActionButtonView; this.workIconView = (ImageView) rootView.findViewById(R.id.work_profile_icon); this.checkBoxView = (ImageView) rootView.findViewById(R.id.quick_contact_checkbox); - mPhotoSize = mContext.getResources().getDimensionPixelSize(R.dimen.contact_photo_size); // Set text height to false on the TextViews so they don't have extra padding. phoneCallDetailsViews.nameView.setElegantTextHeight(false); @@ -249,7 +257,16 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } primaryActionButtonView.setOnClickListener(this); primaryActionView.setOnClickListener(mExpandCollapseListener); - primaryActionView.setOnLongClickListener(longPressListener); + if (mVoicemailPlaybackPresenter != null + && ConfigProviderBindings.get(mContext) + .getBoolean( + CallLogAdapter.ENABLE_CALL_LOG_MULTI_SELECT, + CallLogAdapter.ENABLE_CALL_LOG_MULTI_SELECT_FLAG)) { + primaryActionView.setOnLongClickListener(longPressListener); + quickContactView.setOnLongClickListener(longPressListener); + } else { + primaryActionView.setOnCreateContextMenuListener(this); + } } public static CallLogListItemViewHolder create( @@ -689,36 +706,23 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return; } - final String lookupKey = - info.lookupUri != null ? UriUtils.getLookupKeyFromUri(info.lookupUri) : null; final String displayName = TextUtils.isEmpty(info.name) ? displayNumber : info.name; - final DefaultImageRequest request = - new DefaultImageRequest(displayName, lookupKey, getContactType(), true /* isCircular */); - - if (info.photoId == 0 && info.photoUri != null) { - ContactPhotoManager.getInstance(mContext) - .loadPhoto( - quickContactView, - info.photoUri, - mPhotoSize, - false /* darkTheme */, - true /* isCircular */, - request); - } else { - ContactPhotoManager.getInstance(mContext) - .loadThumbnail( - quickContactView, - info.photoId, - false /* darkTheme */, - true /* isCircular */, - request); - } + ContactPhotoManager.getInstance(mContext) + .loadDialerThumbnailOrPhoto( + quickContactView, + info.lookupUri, + info.photoId, + info.photoUri, + displayName, + getContactType()); } private int getContactType() { int contactType = ContactPhotoManager.TYPE_DEFAULT; if (mCallLogCache.isVoicemailNumber(accountHandle, number)) { contactType = ContactPhotoManager.TYPE_VOICEMAIL; + } else if (isSpam) { + contactType = ContactPhotoManager.TYPE_SPAM; } else if (mCachedNumberLookupService != null && mCachedNumberLookupService.isBusiness(info.sourceType)) { contactType = ContactPhotoManager.TYPE_BUSINESS; @@ -742,6 +746,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder CallSubjectDialog.start( (Activity) mContext, info.photoId, + info.photoUri, info.lookupUri, (String) nameOrNumber /* top line of contact view in call subject dialog */, number, @@ -802,18 +807,26 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } private CallComposerContact buildContact() { - CallComposerContact contact = new CallComposerContact(); - contact.photoId = info.photoId; - contact.photoUri = info.photoUri == null ? null : info.photoUri.toString(); - contact.contactUri = info.lookupUri == null ? null : info.lookupUri.toString(); - contact.nameOrNumber = (String) nameOrNumber; - contact.contactType = getContactType(); - contact.number = number; + CallComposerContact.Builder contact = CallComposerContact.newBuilder(); + contact.setPhotoId(info.photoId); + if (info.photoUri != null) { + contact.setPhotoUri(info.photoUri.toString()); + } + if (info.lookupUri != null) { + contact.setContactUri(info.lookupUri.toString()); + } + if (nameOrNumber != null) { + contact.setNameOrNumber((String) nameOrNumber); + } + contact.setContactType(getContactType()); + contact.setNumber(number); /* second line of contact view. */ - contact.displayNumber = TextUtils.isEmpty(info.name) ? null : displayNumber; + if (!TextUtils.isEmpty(info.name)) { + contact.setDisplayNumber(displayNumber); + } /* phone number type (e.g. mobile) in second line of contact view */ - contact.numberLabel = numberType; - return contact; + contact.setNumberLabel(numberType); + return contact.build(); } private void logCallLogAction(int id) { @@ -876,6 +889,104 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return LightbringerComponent.get(mContext).getLightbringer(); } + @Override + public void onCreateContextMenu( + final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + if (TextUtils.isEmpty(number)) { + return; + } + + if (callType == CallLog.Calls.VOICEMAIL_TYPE) { + menu.setHeaderTitle(mContext.getResources().getText(R.string.voicemail)); + } else { + menu.setHeaderTitle( + PhoneNumberUtilsCompat.createTtsSpannable( + BidiFormatter.getInstance().unicodeWrap(number, TextDirectionHeuristics.LTR))); + } + + menu.add( + ContextMenu.NONE, + R.id.context_menu_copy_to_clipboard, + ContextMenu.NONE, + R.string.action_copy_number_text) + .setOnMenuItemClickListener(this); + + // The edit number before call does not show up if any of the conditions apply: + // 1) Number cannot be called + // 2) Number is the voicemail number + // 3) Number is a SIP address + + if (PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation) + && !mCallLogCache.isVoicemailNumber(accountHandle, number) + && !PhoneNumberHelper.isSipNumber(number)) { + menu.add( + ContextMenu.NONE, + R.id.context_menu_edit_before_call, + ContextMenu.NONE, + R.string.action_edit_number_before_call) + .setOnMenuItemClickListener(this); + } + + if (callType == CallLog.Calls.VOICEMAIL_TYPE + && phoneCallDetailsViews.voicemailTranscriptionView.length() > 0) { + menu.add( + ContextMenu.NONE, + R.id.context_menu_copy_transcript_to_clipboard, + ContextMenu.NONE, + R.string.copy_transcript_text) + .setOnMenuItemClickListener(this); + } + + String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso); + boolean isVoicemailNumber = mCallLogCache.isVoicemailNumber(accountHandle, number); + if (!isVoicemailNumber + && FilteredNumbersUtil.canBlockNumber(mContext, e164Number, number) + && FilteredNumberCompat.canAttemptBlockOperations(mContext)) { + boolean isBlocked = blockId != null; + if (isBlocked) { + menu.add( + ContextMenu.NONE, + R.id.context_menu_unblock, + ContextMenu.NONE, + R.string.call_log_action_unblock_number) + .setOnMenuItemClickListener(this); + } else { + if (isSpamFeatureEnabled) { + if (isSpam) { + menu.add( + ContextMenu.NONE, + R.id.context_menu_report_not_spam, + ContextMenu.NONE, + R.string.call_log_action_remove_spam) + .setOnMenuItemClickListener(this); + menu.add( + ContextMenu.NONE, + R.id.context_menu_block, + ContextMenu.NONE, + R.string.call_log_action_block_number) + .setOnMenuItemClickListener(this); + } else { + menu.add( + ContextMenu.NONE, + R.id.context_menu_block_report_spam, + ContextMenu.NONE, + R.string.call_log_action_block_report_number) + .setOnMenuItemClickListener(this); + } + } else { + menu.add( + ContextMenu.NONE, + R.id.context_menu_block, + ContextMenu.NONE, + R.string.call_log_action_block_number) + .setOnMenuItemClickListener(this); + } + } + } + + Logger.get(mContext).logScreenView(ScreenEvent.Type.CALL_LOG_CONTEXT_MENU, (Activity) mContext); + } + public interface OnClickListener { void onBlockReportSpam( @@ -883,21 +994,21 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder String number, String countryIso, int callType, - int contactSourceType); + ContactSource.Type contactSourceType); void onBlock( String displayNumber, String number, String countryIso, int callType, - int contactSourceType); + ContactSource.Type contactSourceType); void onUnblock( String displayNumber, String number, String countryIso, int callType, - int contactSourceType, + ContactSource.Type contactSourceType, boolean isSpam, Integer blockId); @@ -906,6 +1017,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder String number, String countryIso, int callType, - int contactSourceType); + ContactSource.Type contactSourceType); } } diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java b/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java index c08d2c02b47b648e62bca21f462a74ab710dbfe3..0b4da7521a7422abf34aef6a38d0616d70e30d2b 100644 --- a/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java @@ -57,7 +57,7 @@ public class CallLogNotificationsActivity extends AppCompatActivity { String action = intent.getAction(); switch (action) { case ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION: - MissedCallNotifier.getInstance(this) + MissedCallNotifier.getIstance(this) .sendSmsFromMissedCall( intent.getStringExtra(EXTRA_MISSED_CALL_NUMBER), intent.getData()); break; diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java b/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java index 79a32afe3cc06fd118ea8c983909bf348496403b..e169b8de909121e4a948f035c5af28fba5b962cb 100644 --- a/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java @@ -32,10 +32,10 @@ import android.support.annotation.WorkerThread; import android.support.v4.os.UserManagerCompat; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; -import com.android.contacts.common.GeoUtil; import com.android.dialer.app.R; import com.android.dialer.calllogutils.PhoneNumberDisplayUtil; import com.android.dialer.common.LogUtil; +import com.android.dialer.location.GeoUtil; import com.android.dialer.notification.GroupedNotificationUtil; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; @@ -114,11 +114,6 @@ public class CallLogNotificationsQueryHelper { MissedCallNotifier.NOTIFICATION_TAG); } - /** Update the voice mail notifications. */ - public static void updateVoicemailNotifications(Context context) { - CallLogNotificationsService.updateVoicemailNotifications(context); - } - /** Create a new instance of {@link NewCallsQuery}. */ public static NewCallsQuery createNewCallsQuery( Context context, ContentResolver contentResolver) { diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java index f67837f8a1df90ed9cc4ee511ce4d39b3f3f7a9b..7dfd2cb69967548463423dd2999220f28baf9741 100644 --- a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java @@ -26,7 +26,6 @@ import android.support.annotation.Nullable; import com.android.dialer.common.LogUtil; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.PermissionsUtil; -import me.leolin.shortcutbadger.ShortcutBadger; /** * Provides operations for managing call-related notifications. @@ -47,17 +46,6 @@ public class CallLogNotificationsService extends IntentService { /** Action to mark all the new voicemails as old. */ public static final String ACTION_MARK_NEW_VOICEMAILS_AS_OLD = "com.android.dialer.calllog.ACTION_MARK_NEW_VOICEMAILS_AS_OLD"; - /** Action to update voicemail notifications. */ - public static final String ACTION_UPDATE_VOICEMAIL_NOTIFICATIONS = - "com.android.dialer.calllog.UPDATE_VOICEMAIL_NOTIFICATIONS"; - /** - * Action to update the missed call notifications. - * - *

Includes optional extras {@link #EXTRA_MISSED_CALL_NUMBER} and {@link - * #EXTRA_MISSED_CALL_COUNT}. - */ - public static final String ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS = - "com.android.dialer.calllog.UPDATE_MISSED_CALL_NOTIFICATIONS"; /** Action to mark all the new missed calls as old. */ public static final String ACTION_MARK_NEW_MISSED_CALLS_AS_OLD = @@ -71,22 +59,6 @@ public class CallLogNotificationsService extends IntentService { public static final String ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION = "com.android.dialer.calllog.CALL_BACK_FROM_MISSED_CALL_NOTIFICATION"; - /** - * Extra to be included with {@link #ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS} and {@link - * #ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION} to identify the number to display, call or - * text back. - * - *

It must be a {@link String}. - */ - public static final String EXTRA_MISSED_CALL_NUMBER = "MISSED_CALL_NUMBER"; - /** - * Extra to be included with {@link #ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS} to represent the - * number of missed calls. - * - *

It must be a {@link Integer} - */ - public static final String EXTRA_MISSED_CALL_COUNT = "MISSED_CALL_COUNT"; - /** * Extra to be included with {@link #ACTION_INCOMING_POST_CALL} to represent a post call note. * @@ -109,40 +81,6 @@ public class CallLogNotificationsService extends IntentService { super("CallLogNotificationsService"); } - /** - * Updates notifications for any new voicemails. - * - * @param context a valid context. - */ - public static void updateVoicemailNotifications(Context context) { - if (!TelecomUtil.isDefaultDialer(context)) { - LogUtil.i( - "CallLogNotificationsService.updateVoicemailNotifications", - "not default dialer, ignoring voicemail notifications"); - return; - } - if (TelecomUtil.hasReadWriteVoicemailPermissions(context)) { - Intent serviceIntent = new Intent(context, CallLogNotificationsService.class); - serviceIntent.setAction(CallLogNotificationsService.ACTION_UPDATE_VOICEMAIL_NOTIFICATIONS); - context.startService(serviceIntent); - } - } - - /** - * Updates notifications for any new missed calls. - * - * @param context A valid context. - * @param count The number of new missed calls. - * @param number The phone number of the newest missed call. - */ - public static void updateMissedCallNotifications(Context context, int count, String number) { - Intent serviceIntent = new Intent(context, CallLogNotificationsService.class); - serviceIntent.setAction(CallLogNotificationsService.ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS); - serviceIntent.putExtra(EXTRA_MISSED_CALL_COUNT, count); - serviceIntent.putExtra(EXTRA_MISSED_CALL_NUMBER, number); - context.startService(serviceIntent); - } - public static void insertPostCallNote(Context context, String number, String postCallNote) { Intent serviceIntent = new Intent(context, CallLogNotificationsService.class); serviceIntent.setAction(ACTION_INCOMING_POST_CALL); @@ -165,16 +103,6 @@ public class CallLogNotificationsService extends IntentService { context.startService(serviceIntent); } - public static boolean updateBadgeCount(Context context, int count) { - boolean success = ShortcutBadger.applyCount(context, count); - LogUtil.i( - "CallLogNotificationsService.updateBadgeCount", - "update badge count: %d success: %b", - count, - success); - return success; - } - @Override protected void onHandleIntent(Intent intent) { if (intent == null) { @@ -200,28 +128,21 @@ public class CallLogNotificationsService extends IntentService { mVoicemailQueryHandler.markNewVoicemailsAsOld(intent.getData()); }); break; - case ACTION_UPDATE_VOICEMAIL_NOTIFICATIONS: - DefaultVoicemailNotifier.getInstance(this).updateNotification(); - break; - case ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS: - int count = intent.getIntExtra(EXTRA_MISSED_CALL_COUNT, UNKNOWN_MISSED_CALL_COUNT); - String number = intent.getStringExtra(EXTRA_MISSED_CALL_NUMBER); - MissedCallNotifier.getInstance(this).updateMissedCallNotification(count, number); - updateBadgeCount(this, count); - break; case ACTION_INCOMING_POST_CALL: String note = intent.getStringExtra(EXTRA_POST_CALL_NOTE); String phoneNumber = intent.getStringExtra(EXTRA_POST_CALL_NUMBER); - MissedCallNotifier.getInstance(this).insertPostCallNotification(phoneNumber, note); + MissedCallNotifier.getIstance(this).insertPostCallNotification(phoneNumber, note); break; case ACTION_MARK_NEW_MISSED_CALLS_AS_OLD: CallLogNotificationsQueryHelper.removeMissedCallNotifications(this, intent.getData()); TelecomUtil.cancelMissedCallsNotification(this); break; case ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION: - MissedCallNotifier.getInstance(this) + MissedCallNotifier.getIstance(this) .callBackFromMissedCall( - intent.getStringExtra(EXTRA_MISSED_CALL_NUMBER), intent.getData()); + intent.getStringExtra( + MissedCallNotificationReceiver.EXTRA_NOTIFICATION_PHONE_NUMBER), + intent.getData()); break; default: LogUtil.d("CallLogNotificationsService.onHandleIntent", "could not handle: " + intent); diff --git a/java/com/android/dialer/app/calllog/CallLogReceiver.java b/java/com/android/dialer/app/calllog/CallLogReceiver.java index 8fd1502bc320672258a4753f2cb913da8d1dc179..172d001006b7a68135c72eeb1030f91b1be41f24 100644 --- a/java/com/android/dialer/app/calllog/CallLogReceiver.java +++ b/java/com/android/dialer/app/calllog/CallLogReceiver.java @@ -38,9 +38,11 @@ public class CallLogReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (VoicemailContract.ACTION_NEW_VOICEMAIL.equals(intent.getAction())) { checkVoicemailStatus(context); - CallLogNotificationsService.updateVoicemailNotifications(context); + PendingResult pendingResult = goAsync(); + DefaultVoicemailNotifier.updateVoicemailNotifications(context, pendingResult::finish); } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { - CallLogNotificationsService.updateVoicemailNotifications(context); + PendingResult pendingResult = goAsync(); + DefaultVoicemailNotifier.updateVoicemailNotifications(context, pendingResult::finish); } else { LogUtil.w("CallLogReceiver.onReceive", "could not handle: " + intent); } diff --git a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java b/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java index dfe5776d8bc88a276323720f7ecc014a98d08bb7..58fe6fa2c06c36ca41f1cd565dda59f5de75896c 100644 --- a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java +++ b/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java @@ -16,6 +16,7 @@ package com.android.dialer.app.calllog; +import android.annotation.TargetApi; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -26,11 +27,18 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; +import android.os.PersistableBundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; +import android.support.annotation.WorkerThread; +import android.support.v4.os.BuildCompat; import android.support.v4.util.Pair; +import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.telephony.CarrierConfigManager; +import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; @@ -41,40 +49,62 @@ import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.app.contactinfo.ContactPhotoLoader; import com.android.dialer.app.list.DialtactsPagerAdapter; +import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.blocking.FilteredNumbersUtil; +import com.android.dialer.calllogutils.PhoneAccountUtils; +import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.DialerExecutor.Worker; +import com.android.dialer.common.concurrent.DialerExecutors; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; import com.android.dialer.notification.NotificationChannelManager; import com.android.dialer.notification.NotificationChannelManager.Channel; import com.android.dialer.phonenumbercache.ContactInfo; +import com.android.dialer.telecom.TelecomUtil; import java.util.Iterator; import java.util.List; import java.util.Map; /** Shows a voicemail notification in the status bar. */ -public class DefaultVoicemailNotifier { +public class DefaultVoicemailNotifier implements Worker { public static final String TAG = "VoicemailNotifier"; /** The tag used to identify notifications from this class. */ - static final String NOTIFICATION_TAG = "DefaultVoicemailNotifier"; + static final String VISUAL_VOICEMAIL_NOTIFICATION_TAG = "DefaultVoicemailNotifier"; /** The identifier of the notification of new voicemails. */ - private static final int NOTIFICATION_ID = R.id.notification_voicemail; + private static final int VISUAL_VOICEMAIL_NOTIFICATION_ID = R.id.notification_visual_voicemail; + + private static final int LEGACY_VOICEMAIL_NOTIFICATION_ID = R.id.notification_legacy_voicemail; + private static final String LEGACY_VOICEMAIL_NOTIFICATION_TAG = "legacy_voicemail"; private final Context context; private final CallLogNotificationsQueryHelper queryHelper; + private final FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - DefaultVoicemailNotifier(Context context, CallLogNotificationsQueryHelper queryHelper) { + DefaultVoicemailNotifier( + Context context, + CallLogNotificationsQueryHelper queryHelper, + FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) { this.context = context; this.queryHelper = queryHelper; + this.filteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler; + } + + public DefaultVoicemailNotifier(Context context) { + this( + context, + CallLogNotificationsQueryHelper.getInstance(context), + new FilteredNumberAsyncQueryHandler(context)); } - /** Returns an instance of {@link DefaultVoicemailNotifier}. */ - public static DefaultVoicemailNotifier getInstance(Context context) { - return new DefaultVoicemailNotifier( - context, CallLogNotificationsQueryHelper.getInstance(context)); + @Nullable + @Override + public Void doInBackground(@Nullable Void input) throws Throwable { + updateNotification(); + return null; } /** @@ -85,7 +115,10 @@ public class DefaultVoicemailNotifier { * *

It is not safe to call this method from the main thread. */ - public void updateNotification() { + @VisibleForTesting + @WorkerThread + void updateNotification() { + Assert.isWorkerThread(); // Lookup the list of new voicemails to include in the notification. final List newCalls = queryHelper.getNewVoicemails(); @@ -109,13 +142,15 @@ public class DefaultVoicemailNotifier { NewCall newCall = itr.next(); // Skip notifying for numbers which are blocked. - if (FilteredNumbersUtil.shouldBlockVoicemail( - context, newCall.number, newCall.countryIso, newCall.dateMs)) { + if (!FilteredNumbersUtil.hasRecentEmergencyCall(context) + && filteredNumberAsyncQueryHandler.getBlockedIdSynchronous( + newCall.number, newCall.countryIso) + != null) { itr.remove(); if (newCall.voicemailUri != null) { // Delete the voicemail. - context.getContentResolver().delete(newCall.voicemailUri, null, null); + CallLogAsyncTaskUtil.deleteVoicemailSynchronous(context, newCall.voicemailUri); } continue; } @@ -153,24 +188,112 @@ public class DefaultVoicemailNotifier { .setGroupSummary(true) .setContentIntent(newVoicemailIntent(null)); + if (BuildCompat.isAtLeastO()) { + groupSummary.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); + } + NotificationChannelManager.applyChannel( groupSummary, context, Channel.VOICEMAIL, PhoneAccountHandles.getAccount(context, newCalls.get(0))); - LogUtil.i(TAG, "Creating voicemail notification"); - getNotificationManager().notify(NOTIFICATION_TAG, NOTIFICATION_ID, groupSummary.build()); + LogUtil.i(TAG, "Creating visual voicemail notification"); + getNotificationManager() + .notify( + VISUAL_VOICEMAIL_NOTIFICATION_TAG, + VISUAL_VOICEMAIL_NOTIFICATION_ID, + groupSummary.build()); for (NewCall voicemail : newCalls) { getNotificationManager() .notify( voicemail.callsUri.toString(), - NOTIFICATION_ID, + VISUAL_VOICEMAIL_NOTIFICATION_ID, createNotificationForVoicemail(voicemail, contactInfos)); } } + /** + * Replicates how packages/services/Telephony/NotificationMgr.java handles legacy voicemail + * notification. The notification will not be stackable because no information is available for + * individual voicemails. + */ + @TargetApi(VERSION_CODES.O) + public void notifyLegacyVoicemail( + @NonNull PhoneAccountHandle phoneAccountHandle, + int count, + String voicemailNumber, + PendingIntent callVoicemailIntent, + PendingIntent voicemailSettingIntent) { + Assert.isNotNull(phoneAccountHandle); + Assert.checkArgument(BuildCompat.isAtLeastO()); + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(phoneAccountHandle); + Assert.isNotNull(telephonyManager); + LogUtil.i(TAG, "Creating legacy voicemail notification"); + + PersistableBundle carrierConfig = telephonyManager.getCarrierConfig(); + + String notificationTitle = + context + .getResources() + .getQuantityString(R.plurals.notification_voicemail_title, count, count); + + TelecomManager telecomManager = context.getSystemService(TelecomManager.class); + PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle); + + String notificationText; + PendingIntent pendingIntent; + + if (voicemailSettingIntent != null) { + // If the voicemail number if unknown, instead of calling voicemail, take the user + // to the voicemail settings. + notificationText = context.getString(R.string.notification_voicemail_no_vm_number); + pendingIntent = voicemailSettingIntent; + } else { + if (PhoneAccountUtils.getSubscriptionPhoneAccounts(context).size() > 1) { + notificationText = phoneAccount.getShortDescription().toString(); + } else { + notificationText = + String.format( + context.getString(R.string.notification_voicemail_text_format), + PhoneNumberUtils.formatNumber(voicemailNumber)); + } + pendingIntent = callVoicemailIntent; + } + Notification.Builder builder = new Notification.Builder(context); + builder + .setSmallIcon(android.R.drawable.stat_notify_voicemail) + .setColor(context.getColor(R.color.dialer_theme_color)) + .setWhen(System.currentTimeMillis()) + .setContentTitle(notificationTitle) + .setContentText(notificationText) + .setContentIntent(pendingIntent) + .setSound(telephonyManager.getVoicemailRingtoneUri(phoneAccountHandle)) + .setOngoing( + carrierConfig.getBoolean( + CarrierConfigManager.KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL)); + + if (telephonyManager.isVoicemailVibrationEnabled(phoneAccountHandle)) { + builder.setDefaults(Notification.DEFAULT_VIBRATE); + } + + NotificationChannelManager.applyChannel( + builder, context, Channel.VOICEMAIL, phoneAccountHandle); + Notification notification = builder.build(); + getNotificationManager() + .notify(LEGACY_VOICEMAIL_NOTIFICATION_TAG, LEGACY_VOICEMAIL_NOTIFICATION_ID, notification); + } + + public void cancelLegacyNotification() { + LogUtil.i(TAG, "Clearing legacy voicemail notification"); + getNotificationManager() + .cancel(LEGACY_VOICEMAIL_NOTIFICATION_TAG, LEGACY_VOICEMAIL_NOTIFICATION_ID); + } + /** * Determines which ringtone Uri and Notification defaults to use when updating the notification * for the given call. @@ -268,7 +391,7 @@ public class DefaultVoicemailNotifier { return new Notification.Builder(context) .setSmallIcon(android.R.drawable.stat_notify_voicemail) .setColor(context.getColor(R.color.dialer_theme_color)) - .setGroup(NOTIFICATION_TAG) + .setGroup(VISUAL_VOICEMAIL_NOTIFICATION_TAG) .setOnlyAlertOnce(true) .setAutoCancel(true); } @@ -283,4 +406,41 @@ public class DefaultVoicemailNotifier { intent.putExtra(DialtactsActivity.EXTRA_CLEAR_NEW_VOICEMAILS, true); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } + + /** + * Updates the voicemail notifications displayed. + * + * @param runnable Called when the async update task completes no matter if it succeeds or fails. + * May be null. + */ + static void updateVoicemailNotifications(Context context, Runnable runnable) { + if (!TelecomUtil.isDefaultDialer(context)) { + LogUtil.i( + "DefaultVoicemailNotifier.updateVoicemailNotifications", + "not default dialer, not scheduling update to voicemail notifications"); + return; + } + + DialerExecutors.createNonUiTaskBuilder(new DefaultVoicemailNotifier(context)) + .onSuccess( + output -> { + LogUtil.i( + "DefaultVoicemailNotifier.updateVoicemailNotifications", + "update voicemail notifications successful"); + if (runnable != null) { + runnable.run(); + } + }) + .onFailure( + throwable -> { + LogUtil.i( + "DefaultVoicemailNotifier.updateVoicemailNotifications", + "update voicemail notifications failed"); + if (runnable != null) { + runnable.run(); + } + }) + .build() + .executeParallel(null); + } } diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java index 8b77c3f51949b8e9b71b6d9f08c873097a161407..a94c6781ed837aafd54d23e81eda19c5a2c57669 100644 --- a/java/com/android/dialer/app/calllog/IntentProvider.java +++ b/java/com/android/dialer/app/calllog/IntentProvider.java @@ -24,11 +24,11 @@ import android.provider.ContactsContract; import android.telecom.PhoneAccountHandle; import com.android.contacts.common.model.Contact; import com.android.contacts.common.model.ContactLoader; -import com.android.dialer.callcomposer.nano.CallComposerContact; +import com.android.dialer.callcomposer.CallComposerContact; import com.android.dialer.calldetails.CallDetailsActivity; -import com.android.dialer.calldetails.nano.CallDetailsEntries; +import com.android.dialer.calldetails.CallDetailsEntries; +import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; -import com.android.dialer.callintent.nano.CallInitiationType; import com.android.dialer.lightbringer.LightbringerComponent; import com.android.dialer.util.CallUtil; import com.android.dialer.util.IntentUtil; diff --git a/java/com/android/dialer/app/calllog/MissedCallNotificationReceiver.java b/java/com/android/dialer/app/calllog/MissedCallNotificationReceiver.java index 3a202034e4f6202bc38b2e575c697ad8891f8d25..65bb6fa57c232c1a758d216aac74ce7f267f2fd7 100644 --- a/java/com/android/dialer/app/calllog/MissedCallNotificationReceiver.java +++ b/java/com/android/dialer/app/calllog/MissedCallNotificationReceiver.java @@ -13,11 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.android.dialer.app.calllog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.support.v4.util.Pair; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.DialerExecutors; +import me.leolin.shortcutbadger.ShortcutBadger; /** * Receives broadcasts that should trigger a refresh of the missed call notification. This includes @@ -44,7 +49,36 @@ public class MissedCallNotificationReceiver extends BroadcastReceiver { int count = intent.getIntExtra( EXTRA_NOTIFICATION_COUNT, CallLogNotificationsService.UNKNOWN_MISSED_CALL_COUNT); - String number = intent.getStringExtra(EXTRA_NOTIFICATION_PHONE_NUMBER); - CallLogNotificationsService.updateMissedCallNotifications(context, count, number); + String phoneNumber = intent.getStringExtra(EXTRA_NOTIFICATION_PHONE_NUMBER); + + PendingResult pendingResult = goAsync(); + + DialerExecutors.createNonUiTaskBuilder(MissedCallNotifier.getIstance(context)) + .onSuccess( + output -> { + LogUtil.i( + "MissedCallNotificationReceiver.onReceive", + "update missed call notifications successful"); + updateBadgeCount(context, count); + pendingResult.finish(); + }) + .onFailure( + throwable -> { + LogUtil.i( + "MissedCallNotificationReceiver.onReceive", + "update missed call notifications failed"); + pendingResult.finish(); + }) + .build() + .executeParallel(new Pair<>(count, phoneNumber)); + } + + private static void updateBadgeCount(Context context, int count) { + boolean success = ShortcutBadger.applyCount(context, count); + LogUtil.i( + "MissedCallNotificationReceiver.updateBadgeCount", + "update badge count: %d success: %b", + count, + success); } } diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java index aa04d81eb62bdd20b52f55a22a95129f531d0cb8..dd13298bc3ff5cfcd3f7566aa6da60b3e5c4ddff 100644 --- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java +++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java @@ -31,6 +31,7 @@ import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import android.support.v4.os.UserManagerCompat; +import android.support.v4.util.Pair; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; import android.text.TextUtils; @@ -41,9 +42,10 @@ import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.app.contactinfo.ContactPhotoLoader; import com.android.dialer.app.list.DialtactsPagerAdapter; +import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; -import com.android.dialer.callintent.nano.CallInitiationType; import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.DialerExecutor.Worker; import com.android.dialer.notification.NotificationChannelManager; import com.android.dialer.notification.NotificationChannelManager.Channel; import com.android.dialer.phonenumbercache.ContactInfo; @@ -55,7 +57,7 @@ import java.util.List; import java.util.Set; /** Creates a notification for calls that the user missed (neither answered nor rejected). */ -public class MissedCallNotifier { +public class MissedCallNotifier implements Worker, Void> { /** The tag used to identify notifications from this class. */ static final String NOTIFICATION_TAG = "MissedCallNotifier"; @@ -72,11 +74,15 @@ public class MissedCallNotifier { this.callLogNotificationsQueryHelper = callLogNotificationsQueryHelper; } - /** Returns an instance of {@link MissedCallNotifier}. */ - public static MissedCallNotifier getInstance(Context context) { - CallLogNotificationsQueryHelper callLogNotificationsQueryHelper = - CallLogNotificationsQueryHelper.getInstance(context); - return new MissedCallNotifier(context, callLogNotificationsQueryHelper); + static MissedCallNotifier getIstance(Context context) { + return new MissedCallNotifier(context, CallLogNotificationsQueryHelper.getInstance(context)); + } + + @Nullable + @Override + public Void doInBackground(@Nullable Pair input) throws Throwable { + updateMissedCallNotification(input.first, input.second); + return null; } /** @@ -88,8 +94,9 @@ public class MissedCallNotifier { * @param number the phone number of the most recent call to display if the call log cannot be * accessed. May be null if unknown. */ + @VisibleForTesting @WorkerThread - public void updateMissedCallNotification(int count, @Nullable String number) { + void updateMissedCallNotification(int count, @Nullable String number) { final int titleResId; CharSequence expandedText; // The text in the notification's line 1 and 2. @@ -375,7 +382,7 @@ public class MissedCallNotifier { private PendingIntent createCallBackPendingIntent(String number, @NonNull Uri callUri) { Intent intent = new Intent(context, CallLogNotificationsService.class); intent.setAction(CallLogNotificationsService.ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION); - intent.putExtra(CallLogNotificationsService.EXTRA_MISSED_CALL_NUMBER, number); + intent.putExtra(MissedCallNotificationReceiver.EXTRA_NOTIFICATION_PHONE_NUMBER, number); intent.setData(callUri); // Use FLAG_UPDATE_CURRENT to make sure any previous pending intent is updated with the new // extra. diff --git a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java index bc78eda0280a0ab0238701fb71c7c491474e2b5c..0c720775a9238fedbe937f45ccdbf13a66fe8644 100644 --- a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java +++ b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java @@ -25,13 +25,14 @@ import android.support.v4.content.ContextCompat; import android.telecom.PhoneAccount; import android.text.TextUtils; import android.text.format.DateUtils; +import android.text.util.Linkify; import android.view.View; import android.widget.TextView; import com.android.dialer.app.R; import com.android.dialer.app.calllog.calllogcache.CallLogCache; import com.android.dialer.calllogutils.PhoneCallDetails; +import com.android.dialer.logging.ContactSource; import com.android.dialer.oem.MotorolaUtils; -import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo; import com.android.dialer.phonenumberutil.PhoneNumberHelper; import com.android.dialer.util.DialerUtils; import java.util.ArrayList; @@ -142,6 +143,8 @@ public class PhoneCallDetailsHelper { views.nameView.setText(nameText); if (isVoicemail) { + int relevantLinkTypes = Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS | Linkify.WEB_URLS; + views.voicemailTranscriptionView.setAutoLinkMask(relevantLinkTypes); views.voicemailTranscriptionView.setText( TextUtils.isEmpty(details.transcription) ? null : details.transcription); } @@ -230,7 +233,7 @@ public class PhoneCallDetailsHelper { return false; } // For caller ID provided by Cequint we want to show the geo location. - if (details.sourceType == CachedContactInfo.SOURCE_TYPE_CEQUINT_CALLER_ID) { + if (details.sourceType == ContactSource.Type.SOURCE_TYPE_CEQUINT_CALLER_ID) { return true; } // Don't bother showing geo location for contacts. diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java index 5e820a7501bcc798b0ac5e793706a2bfc9af84c2..893d6bed9e5019284b5542e054fea08649c5d905 100644 --- a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java +++ b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java @@ -31,30 +31,21 @@ import com.android.dialer.app.voicemail.VoicemailAudioManager; import com.android.dialer.app.voicemail.VoicemailErrorManager; import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter; import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.util.PermissionsUtil; public class VisualVoicemailCallLogFragment extends CallLogFragment { private final ContentObserver mVoicemailStatusObserver = new CustomContentObserver(); private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; - private VoicemailErrorManager mVoicemailAlertManager; + private VoicemailErrorManager mVoicemailErrorManager; public VisualVoicemailCallLogFragment() { super(CallLog.Calls.VOICEMAIL_TYPE); } - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - mVoicemailPlaybackPresenter = VoicemailPlaybackPresenter.getInstance(getActivity(), state); - getActivity() - .getContentResolver() - .registerContentObserver( - VoicemailContract.Status.CONTENT_URI, true, mVoicemailStatusObserver); - } - @Override protected VoicemailPlaybackPresenter getVoicemailPlaybackPresenter() { return mVoicemailPlaybackPresenter; @@ -62,15 +53,37 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment { @Override public void onActivityCreated(Bundle savedInstanceState) { + mVoicemailPlaybackPresenter = + VoicemailPlaybackPresenter.getInstance(getActivity(), savedInstanceState); + + if (PermissionsUtil.hasReadVoicemailPermissions(getContext()) + && PermissionsUtil.hasAddVoicemailPermissions(getContext())) { + getActivity() + .getContentResolver() + .registerContentObserver( + VoicemailContract.Status.CONTENT_URI, true, mVoicemailStatusObserver); + } else { + LogUtil.w( + "VisualVoicemailCallLogFragment.onActivityCreated", + "read voicemail permission unavailable."); + } super.onActivityCreated(savedInstanceState); - mVoicemailAlertManager = + mVoicemailErrorManager = new VoicemailErrorManager(getContext(), getAdapter().getAlertManager(), mModalAlertManager); - getActivity() - .getContentResolver() - .registerContentObserver( - VoicemailContract.Status.CONTENT_URI, - true, - mVoicemailAlertManager.getContentObserver()); + + if (PermissionsUtil.hasReadVoicemailPermissions(getContext()) + && PermissionsUtil.hasAddVoicemailPermissions(getContext())) { + getActivity() + .getContentResolver() + .registerContentObserver( + VoicemailContract.Status.CONTENT_URI, + true, + mVoicemailErrorManager.getContentObserver()); + } else { + LogUtil.w( + "VisualVoicemailCallLogFragment.onActivityCreated", + "read voicemail permission unavailable."); + } } @Override @@ -84,13 +97,13 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment { public void onResume() { super.onResume(); mVoicemailPlaybackPresenter.onResume(); - mVoicemailAlertManager.onResume(); + mVoicemailErrorManager.onResume(); } @Override public void onPause() { mVoicemailPlaybackPresenter.onPause(); - mVoicemailAlertManager.onPause(); + mVoicemailErrorManager.onPause(); super.onPause(); } @@ -98,8 +111,9 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment { public void onDestroy() { getActivity() .getContentResolver() - .unregisterContentObserver(mVoicemailAlertManager.getContentObserver()); + .unregisterContentObserver(mVoicemailErrorManager.getContentObserver()); mVoicemailPlaybackPresenter.onDestroy(); + mVoicemailErrorManager.onDestroy(); getActivity().getContentResolver().unregisterContentObserver(mVoicemailStatusObserver); super.onDestroy(); } @@ -121,7 +135,9 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment { LogUtil.enterBlock("VisualVoicemailCallLogFragment.onPageSelected"); super.onVisible(); if (getActivity() != null) { - getActivity().sendBroadcast(new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL)); + Intent intent = new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL); + intent.setPackage(getActivity().getPackageName()); + getActivity().sendBroadcast(intent); Logger.get(getActivity()).logImpression(DialerImpression.Type.VVM_TAB_VIEWED); getActivity().setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM); } diff --git a/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java b/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java index 2aa3fb282a5322919f83192f1c4c111218379a38..777f4c79f6721037a85019c3cfd0476957be526b 100644 --- a/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java +++ b/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java @@ -20,14 +20,12 @@ import android.content.AsyncQueryHandler; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; -import android.content.Intent; import android.net.Uri; import android.provider.CallLog.Calls; import android.support.annotation.MainThread; import android.support.annotation.Nullable; import com.android.dialer.app.R; import com.android.dialer.common.Assert; -import com.android.dialer.common.LogUtil; import com.android.dialer.notification.GroupedNotificationUtil; /** Handles asynchronous queries to the call log for voicemail. */ @@ -76,20 +74,7 @@ public class VoicemailQueryHandler extends AsyncQueryHandler { GroupedNotificationUtil.removeNotification( mContext.getSystemService(NotificationManager.class), voicemailUri != null ? voicemailUri.toString() : null, - R.id.notification_voicemail, - DefaultVoicemailNotifier.NOTIFICATION_TAG); - } - - @Override - protected void onUpdateComplete(int token, Object cookie, int result) { - if (token == UPDATE_MARK_VOICEMAILS_AS_OLD_TOKEN) { - if (mContext != null) { - Intent serviceIntent = new Intent(mContext, CallLogNotificationsService.class); - serviceIntent.setAction(CallLogNotificationsService.ACTION_UPDATE_VOICEMAIL_NOTIFICATIONS); - mContext.startService(serviceIntent); - } else { - LogUtil.w(TAG, "Unknown update completed: ignoring: " + token); - } - } + R.id.notification_visual_voicemail, + DefaultVoicemailNotifier.VISUAL_VOICEMAIL_NOTIFICATION_TAG); } } diff --git a/java/com/android/dialer/app/contactinfo/ContactInfoCache.java b/java/com/android/dialer/app/contactinfo/ContactInfoCache.java index 85a9c3ef1774b09ca7bb268728afaa7654e6b2ce..e561b560787b3a4d414f78ac178b29f18f31f86b 100644 --- a/java/com/android/dialer/app/contactinfo/ContactInfoCache.java +++ b/java/com/android/dialer/app/contactinfo/ContactInfoCache.java @@ -23,10 +23,12 @@ import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.ContactSource.Type; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; import com.android.dialer.util.ExpirableCache; import java.lang.ref.WeakReference; +import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.PriorityBlockingQueue; @@ -76,6 +78,8 @@ public class ContactInfoCache { break; case START_THREAD: reference.startRequestProcessing(); + break; + default: // fall out } } } @@ -124,7 +128,7 @@ public class ContactInfoCache { enqueueRequest(number, countryIso, callLogContactInfo, /* immediate */ false, requestType); } - if (info == ContactInfo.EMPTY) { + if (Objects.equals(info, ContactInfo.EMPTY)) { // Use the cached contact info from the call log. info = callLogContactInfo; } @@ -152,11 +156,15 @@ public class ContactInfoCache { ContactInfo info; if (request.isLocalRequest()) { info = mContactInfoHelper.lookupNumber(request.number, request.countryIso); - // TODO: Maybe skip look up if it's already available in cached number lookup service. - long start = SystemClock.elapsedRealtime(); - mContactInfoHelper.updateFromCequintCallerId(info, request.number); - long time = SystemClock.elapsedRealtime() - start; - LogUtil.d("ContactInfoCache.queryContactInfo", "Cequint Caller Id look up takes %d ms", time); + if (!info.contactExists) { + // TODO: Maybe skip look up if it's already available in cached number lookup + // service. + long start = SystemClock.elapsedRealtime(); + mContactInfoHelper.updateFromCequintCallerId(info, request.number); + long time = SystemClock.elapsedRealtime() - start; + LogUtil.d( + "ContactInfoCache.queryContactInfo", "Cequint Caller Id look up takes %d ms", time); + } if (request.type == ContactInfoRequest.TYPE_LOCAL_AND_REMOTE) { if (!mContactInfoHelper.hasName(info)) { enqueueRequest( @@ -183,7 +191,7 @@ public class ContactInfoCache { new NumberWithCountryIso(request.number, request.countryIso); ContactInfo existingInfo = mCache.getPossiblyExpired(numberCountryIso); - final boolean isRemoteSource = info.sourceType != 0; + final boolean isRemoteSource = info.sourceType != Type.UNKNOWN_SOURCE_TYPE; // Don't force redraw if existing info in the cache is equal to {@link ContactInfo#EMPTY} // to avoid updating the data set for every new row that is scrolled into view. @@ -191,7 +199,8 @@ public class ContactInfoCache { // Exception: Photo uris for contacts from remote sources are not cached in the call log // cache, so we have to force a redraw for these contacts regardless. boolean updated = - (existingInfo != ContactInfo.EMPTY || isRemoteSource) && !info.equals(existingInfo); + (!Objects.equals(existingInfo, ContactInfo.EMPTY) || isRemoteSource) + && !info.equals(existingInfo); // Store the data in the cache so that the UI thread can use to display it. Store it // even if it has not changed so that it is marked as not expired. @@ -346,7 +355,7 @@ public class ContactInfoCache { shouldRedraw |= queryContactInfo(request); if (shouldRedraw && (mUpdateRequests.isEmpty() - || request.isLocalRequest() && !mUpdateRequests.peek().isLocalRequest())) { + || (request.isLocalRequest() && !mUpdateRequests.peek().isLocalRequest()))) { shouldRedraw = false; mHandler.sendEmptyMessage(REDRAW); } diff --git a/java/com/android/dialer/app/contactinfo/ContactPhotoLoader.java b/java/com/android/dialer/app/contactinfo/ContactPhotoLoader.java index 71e4a16adf2c4f00b50282a725a7fe52e5ede86e..4c8e32a41ccce16f5cabeea866db2f9ef46347cf 100644 --- a/java/com/android/dialer/app/contactinfo/ContactPhotoLoader.java +++ b/java/com/android/dialer/app/contactinfo/ContactPhotoLoader.java @@ -25,11 +25,11 @@ import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; -import com.android.contacts.common.GeoUtil; import com.android.contacts.common.lettertiles.LetterTileDrawable; import com.android.dialer.app.R; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; +import com.android.dialer.location.GeoUtil; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; import java.io.IOException; diff --git a/java/com/android/dialer/app/dialpad/DialpadFragment.java b/java/com/android/dialer/app/dialpad/DialpadFragment.java index 80be8fe05dda8a8f95eeff70c9c698cf941d2b21..e9d57b3995f341a5b79821958c2301e3f3f8b94a 100644 --- a/java/com/android/dialer/app/dialpad/DialpadFragment.java +++ b/java/com/android/dialer/app/dialpad/DialpadFragment.java @@ -69,7 +69,6 @@ import android.widget.ListView; import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.TextView; -import com.android.contacts.common.GeoUtil; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.contacts.common.util.StopWatch; import com.android.contacts.common.widget.FloatingActionButtonController; @@ -78,12 +77,13 @@ import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; import com.android.dialer.app.SpecialCharSequenceMgr; import com.android.dialer.app.calllog.CallLogAsync; +import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; -import com.android.dialer.callintent.nano.CallInitiationType; import com.android.dialer.calllogutils.PhoneAccountUtils; import com.android.dialer.common.LogUtil; import com.android.dialer.dialpadview.DialpadKeyButton; import com.android.dialer.dialpadview.DialpadView; +import com.android.dialer.location.GeoUtil; import com.android.dialer.proguard.UsedByReflection; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.CallUtil; @@ -447,7 +447,7 @@ public class DialpadFragment extends Fragment setFormattedDigits(converted, null); return true; } else { - if (!PermissionsUtil.hasContactsPermissions(getActivity())) { + if (!PermissionsUtil.hasContactsReadPermissions(getActivity())) { return false; } String type = intent.getType(); @@ -1189,7 +1189,6 @@ public class DialpadFragment extends Fragment // Just call 'scaleIn()' method if the mFloatingActionButtonController was not already // previously visible. mFloatingActionButtonController.scaleIn(0); - mFloatingActionButtonController.setVisible(true); } mDialpadChooser.setVisibility(View.GONE); } @@ -1410,10 +1409,10 @@ public class DialpadFragment extends Fragment public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); final DialtactsActivity activity = (DialtactsActivity) getActivity(); - final DialpadView dialpadView = (DialpadView) getView().findViewById(R.id.dialpad_view); - if (activity == null) { + if (activity == null || getView() == null) { return; } + final DialpadView dialpadView = (DialpadView) getView().findViewById(R.id.dialpad_view); if (!hidden && !isDialpadChooserVisible()) { if (mAnimate) { dialpadView.animateShow(); diff --git a/java/com/android/dialer/app/dialpad/SmartDialCursorLoader.java b/java/com/android/dialer/app/dialpad/SmartDialCursorLoader.java index f3a93f916f4781686359493f0c90980c66eac42f..a0c8b18d3e984270b98044e45497d08f2b0a0504 100644 --- a/java/com/android/dialer/app/dialpad/SmartDialCursorLoader.java +++ b/java/com/android/dialer/app/dialpad/SmartDialCursorLoader.java @@ -20,8 +20,8 @@ import android.content.AsyncTaskLoader; import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; -import android.util.Log; import com.android.contacts.common.list.PhoneNumberListAdapter.PhoneQuery; +import com.android.dialer.common.LogUtil; import com.android.dialer.database.Database; import com.android.dialer.database.DialerDatabaseHelper; import com.android.dialer.database.DialerDatabaseHelper.ContactNumber; @@ -43,8 +43,6 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { private String mQuery; private SmartDialNameMatcher mNameMatcher; - private ForceLoadContentObserver mObserver; - private boolean mShowEmptyListForNullQuery = true; public SmartDialCursorLoader(Context context) { @@ -59,7 +57,7 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { */ public void configureQuery(String query) { if (DEBUG) { - Log.v(TAG, "Configure new query to be " + query); + LogUtil.v(TAG, "Configure new query to be " + query); } mQuery = SmartDialNameMatcher.normalizeNumber(query, SmartDialPrefix.getMap()); @@ -76,10 +74,10 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { @Override public Cursor loadInBackground() { if (DEBUG) { - Log.v(TAG, "Load in background " + mQuery); + LogUtil.v(TAG, "Load in background " + mQuery); } - if (!PermissionsUtil.hasContactsPermissions(mContext)) { + if (!PermissionsUtil.hasContactsReadPermissions(mContext)) { return new MatrixCursor(PhoneQuery.PROJECTION_PRIMARY); } @@ -90,7 +88,7 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { dialerDatabaseHelper.getLooseMatches(mQuery, mNameMatcher); if (DEBUG) { - Log.v(TAG, "Loaded matches " + String.valueOf(allMatches.size())); + LogUtil.v(TAG, "Loaded matches " + allMatches.size()); } /** Constructs a cursor for the returned array of results. */ @@ -121,13 +119,6 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { Cursor oldCursor = mCursor; mCursor = cursor; - if (mObserver == null) { - mObserver = new ForceLoadContentObserver(); - mContext - .getContentResolver() - .registerContentObserver(DialerDatabaseHelper.SMART_DIAL_UPDATED_URI, true, mObserver); - } - if (isStarted()) { /** If the Loader is in a started state, deliver the results to the client. */ super.deliverResult(cursor); @@ -162,11 +153,6 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { /** Ensure the loader has been stopped. */ onStopLoading(); - if (mObserver != null) { - mContext.getContentResolver().unregisterContentObserver(mObserver); - mObserver = null; - } - /** Release all previously saved query results. */ if (mCursor != null) { releaseResources(mCursor); @@ -178,11 +164,6 @@ public class SmartDialCursorLoader extends AsyncTaskLoader { public void onCanceled(Cursor cursor) { super.onCanceled(cursor); - if (mObserver != null) { - mContext.getContentResolver().unregisterContentObserver(mObserver); - mObserver = null; - } - /** The load has been canceled, so we should release the resources associated with 'data'. */ releaseResources(cursor); } diff --git a/java/com/android/dialer/app/filterednumber/BlockedNumbersAdapter.java b/java/com/android/dialer/app/filterednumber/BlockedNumbersAdapter.java index b9381331c0a6dc6a016fb987e4cfb5d6b870ffe2..dbd4e868c85aefa65584a7ffc63e7a4c2a36fc3e 100644 --- a/java/com/android/dialer/app/filterednumber/BlockedNumbersAdapter.java +++ b/java/com/android/dialer/app/filterednumber/BlockedNumbersAdapter.java @@ -21,12 +21,12 @@ import android.database.Cursor; import android.telephony.PhoneNumberUtils; import android.view.View; import com.android.contacts.common.ContactPhotoManager; -import com.android.contacts.common.GeoUtil; import com.android.dialer.app.R; import com.android.dialer.blocking.BlockNumberDialogFragment; import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns; +import com.android.dialer.location.GeoUtil; +import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.InteractionEvent; import com.android.dialer.phonenumbercache.ContactInfoHelper; public class BlockedNumbersAdapter extends NumbersAdapter { @@ -55,8 +55,6 @@ public class BlockedNumbersAdapter extends NumbersAdapter { final String countryIso = cursor.getString(cursor.getColumnIndex(FilteredNumberColumns.COUNTRY_ISO)); final String number = cursor.getString(cursor.getColumnIndex(FilteredNumberColumns.NUMBER)); - final String normalizedNumber = - cursor.getString(cursor.getColumnIndex(FilteredNumberColumns.NORMALIZED_NUMBER)); final View deleteButton = view.findViewById(R.id.delete_button); deleteButton.setOnClickListener( diff --git a/java/com/android/dialer/app/filterednumber/BlockedNumbersSettingsActivity.java b/java/com/android/dialer/app/filterednumber/BlockedNumbersSettingsActivity.java index 9ec6042c04a3334234884a08207c364b0c951410..9310fcb22d2865fe3ffddad26a31fdc063935579 100644 --- a/java/com/android/dialer/app/filterednumber/BlockedNumbersSettingsActivity.java +++ b/java/com/android/dialer/app/filterednumber/BlockedNumbersSettingsActivity.java @@ -22,7 +22,7 @@ import com.android.dialer.app.R; import com.android.dialer.app.list.BlockedListSearchFragment; import com.android.dialer.app.list.SearchFragment; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.ScreenEvent; +import com.android.dialer.logging.ScreenEvent; public class BlockedNumbersSettingsActivity extends AppCompatActivity implements SearchFragment.HostInterface { diff --git a/java/com/android/dialer/app/filterednumber/ViewNumbersToImportAdapter.java b/java/com/android/dialer/app/filterednumber/ViewNumbersToImportAdapter.java index 5228a1d7901a830440d623c43f7f2fcad9725163..313efb4d74d11688313614b06b82691d5a07825a 100644 --- a/java/com/android/dialer/app/filterednumber/ViewNumbersToImportAdapter.java +++ b/java/com/android/dialer/app/filterednumber/ViewNumbersToImportAdapter.java @@ -20,9 +20,9 @@ import android.content.Context; import android.database.Cursor; import android.view.View; import com.android.contacts.common.ContactPhotoManager; -import com.android.contacts.common.GeoUtil; import com.android.dialer.app.R; import com.android.dialer.blocking.FilteredNumbersUtil; +import com.android.dialer.location.GeoUtil; import com.android.dialer.phonenumbercache.ContactInfoHelper; public class ViewNumbersToImportAdapter extends NumbersAdapter { diff --git a/java/com/android/dialer/app/list/BlockedListSearchAdapter.java b/java/com/android/dialer/app/list/BlockedListSearchAdapter.java index a90ce7a0df114985f972fc9b9c628ac86e0aa719..96d02d7bf0b99fc2b39e4721ed66bb3d8b7973f8 100644 --- a/java/com/android/dialer/app/list/BlockedListSearchAdapter.java +++ b/java/com/android/dialer/app/list/BlockedListSearchAdapter.java @@ -19,10 +19,10 @@ import android.content.Context; import android.content.res.Resources; import android.database.Cursor; import android.view.View; -import com.android.contacts.common.GeoUtil; import com.android.contacts.common.list.ContactListItemView; import com.android.dialer.app.R; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; +import com.android.dialer.location.GeoUtil; /** List adapter to display search results for adding a blocked number. */ public class BlockedListSearchAdapter extends RegularSearchListAdapter { diff --git a/java/com/android/dialer/app/list/BlockedListSearchFragment.java b/java/com/android/dialer/app/list/BlockedListSearchFragment.java index 2129981c037026b92de4636dd2518744b3f65691..8d42221c0153b1c8677fbfc83f0c8de51332a461 100644 --- a/java/com/android/dialer/app/list/BlockedListSearchFragment.java +++ b/java/com/android/dialer/app/list/BlockedListSearchFragment.java @@ -23,13 +23,11 @@ import android.telephony.PhoneNumberUtils; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; import android.util.TypedValue; import android.view.View; import android.widget.AdapterView; import android.widget.EditText; import android.widget.Toast; -import com.android.contacts.common.GeoUtil; import com.android.contacts.common.list.ContactEntryListAdapter; import com.android.contacts.common.util.ContactDisplayUtils; import com.android.dialer.app.R; @@ -37,14 +35,14 @@ import com.android.dialer.app.widget.SearchEditTextLayout; import com.android.dialer.blocking.BlockNumberDialogFragment; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener; +import com.android.dialer.common.LogUtil; +import com.android.dialer.location.GeoUtil; +import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.InteractionEvent; public class BlockedListSearchFragment extends RegularSearchFragment implements BlockNumberDialogFragment.Callback { - private static final String TAG = BlockedListSearchFragment.class.getSimpleName(); - private final TextWatcher mPhoneSearchQueryTextListener = new TextWatcher() { @Override @@ -152,7 +150,9 @@ public class BlockedListSearchFragment extends RegularSearchFragment blockNumber(number); break; default: - Log.w(TAG, "Ignoring unsupported shortcut type: " + shortcutType); + LogUtil.w( + "BlockedListSearchFragment.onItemClick", + "ignoring unsupported shortcut type: " + shortcutType); break; } } @@ -205,7 +205,9 @@ public class BlockedListSearchFragment extends RegularSearchFragment @Override public void onUnfilterNumberSuccess() { - Log.wtf(TAG, "Unblocked a number from the BlockedListSearchFragment"); + LogUtil.e( + "BlockedListSearchFragment.onUnfilterNumberSuccess", + "unblocked a number from the BlockedListSearchFragment"); goBack(); } diff --git a/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java b/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java index 542501cfd843daeba0800a284e5f33bc9e2a2fb5..537f488d539f218fc5a59296b8ae9a51fe4c809b 100644 --- a/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java +++ b/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java @@ -24,11 +24,11 @@ import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; import android.view.View; import android.view.ViewGroup; -import com.android.contacts.common.GeoUtil; import com.android.contacts.common.list.ContactListItemView; import com.android.contacts.common.list.PhoneNumberListAdapter; import com.android.contacts.common.util.ContactDisplayUtils; import com.android.dialer.app.R; +import com.android.dialer.location.GeoUtil; import com.android.dialer.util.CallUtil; /** @@ -47,11 +47,13 @@ public class DialerPhoneNumberListAdapter extends PhoneNumberListAdapter { public static final int SHORTCUT_MAKE_VIDEO_CALL = 4; public static final int SHORTCUT_BLOCK_NUMBER = 5; public static final int SHORTCUT_COUNT = 6; + private final boolean[] mShortcutEnabled = new boolean[SHORTCUT_COUNT]; private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance(); + private final boolean mVideoCallingEnabled; + private final String mCountryIso; + private String mFormattedQueryString; - private String mCountryIso; - private boolean mVideoCallingEnabled = false; public DialerPhoneNumberListAdapter(Context context) { super(context); @@ -108,7 +110,8 @@ public class DialerPhoneNumberListAdapter extends PhoneNumberListAdapter { return convertView; } else { final ContactListItemView v = - new ContactListItemView(getContext(), null, mVideoCallingEnabled); + new ContactListItemView( + getContext(), null, mVideoCallingEnabled, isCallAndShareEnabled()); assignShortcutToView(v, shortcutType); return v; } @@ -123,6 +126,7 @@ public class DialerPhoneNumberListAdapter extends PhoneNumberListAdapter { final ContactListItemView view = super.newView(context, partition, cursor, position, parent); view.setSupportVideoCallIcon(mVideoCallingEnabled); + view.setSupportCallAndShareIcon(isCallAndShareEnabled()); return view; } diff --git a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java index 3b700d81bd2d96968b005229e447e3959287650f..dba3d3a93a4a454da82ae72f89f906ae4afa7e0f 100644 --- a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java +++ b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java @@ -24,9 +24,13 @@ import android.support.v13.app.FragmentPagerAdapter; import android.view.ViewGroup; import com.android.dialer.app.calllog.CallLogFragment; import com.android.dialer.app.calllog.VisualVoicemailCallLogFragment; +import com.android.dialer.calllog.CallLogComponent; +import com.android.dialer.calllog.CallLogFramework; +import com.android.dialer.calllog.ui.NewCallLogFragment; import com.android.dialer.common.Assert; import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; +import com.android.dialer.contactsfragment.ContactsFragment; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.speeddial.SpeedDialFragment; import com.android.dialer.util.ViewUtil; @@ -54,11 +58,14 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter { private final List fragments = new ArrayList<>(); private final String[] tabTitles; private final boolean useNewSpeedDialTab; - + private final boolean useNewCallLogTab; + private final boolean useNewContactsTab; private OldSpeedDialFragment oldSpeedDialFragment; private SpeedDialFragment speedDialFragment; private CallLogFragment callLogFragment; - private AllContactsFragment contactsFragment; + private NewCallLogFragment newCallLogFragment; + private AllContactsFragment oldContactsFragment; + private ContactsFragment contactsFragment; private CallLogFragment voicemailFragment; public boolean hasActiveVoicemailProvider; @@ -68,6 +75,10 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter { super(fm); useNewSpeedDialTab = ConfigProviderBindings.get(context).getBoolean("enable_new_favorites_tab", false); + CallLogFramework callLogFramework = CallLogComponent.get(context).callLogFramework(); + useNewCallLogTab = callLogFramework.isNewCallLogEnabled(context); + useNewContactsTab = + ConfigProviderBindings.get(context).getBoolean("enable_new_contacts_tab", false); this.tabTitles = tabTitles; hasActiveVoicemailProvider = hasVoicemailProvider; fragments.addAll(Collections.nCopies(TAB_COUNT_WITH_VOICEMAIL, null)); @@ -95,15 +106,29 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter { return oldSpeedDialFragment; } case TAB_INDEX_HISTORY: - if (callLogFragment == null) { - callLogFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL); + if (useNewCallLogTab) { + if (newCallLogFragment == null) { + newCallLogFragment = new NewCallLogFragment(); + } + return newCallLogFragment; + } else { + if (callLogFragment == null) { + callLogFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL); + } + return callLogFragment; } - return callLogFragment; case TAB_INDEX_ALL_CONTACTS: - if (contactsFragment == null) { - contactsFragment = new AllContactsFragment(); + if (useNewContactsTab) { + if (contactsFragment == null) { + contactsFragment = new ContactsFragment(); + } + return contactsFragment; + } else { + if (oldContactsFragment == null) { + oldContactsFragment = new AllContactsFragment(); + } + return oldContactsFragment; } - return contactsFragment; case TAB_INDEX_VOICEMAIL: if (voicemailFragment == null) { voicemailFragment = new VisualVoicemailCallLogFragment(); @@ -131,8 +156,12 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter { speedDialFragment = (SpeedDialFragment) fragment; } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_HISTORY) { callLogFragment = (CallLogFragment) fragment; + } else if (fragment instanceof NewCallLogFragment) { + newCallLogFragment = (NewCallLogFragment) fragment; + } else if (fragment instanceof ContactsFragment) { + contactsFragment = (ContactsFragment) fragment; } else if (fragment instanceof AllContactsFragment) { - contactsFragment = (AllContactsFragment) fragment; + oldContactsFragment = (AllContactsFragment) fragment; } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) { voicemailFragment = (CallLogFragment) fragment; LogUtil.v("ViewPagerAdapter.instantiateItem", voicemailFragment.toString()); diff --git a/java/com/android/dialer/app/list/ListsFragment.java b/java/com/android/dialer/app/list/ListsFragment.java index bf29ef3107a5dce9fdf6e8cd47c5a93229d36b89..8dd52a9d49676d3c3a4900d40dc9c0680e9b5471 100644 --- a/java/com/android/dialer/app/list/ListsFragment.java +++ b/java/com/android/dialer/app/list/ListsFragment.java @@ -44,10 +44,11 @@ import com.android.dialer.app.voicemail.error.VoicemailStatusCorruptionHandler; import com.android.dialer.app.voicemail.error.VoicemailStatusCorruptionHandler.Source; import com.android.dialer.common.LogUtil; import com.android.dialer.database.CallLogQueryHandler; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; -import com.android.dialer.logging.nano.ScreenEvent; +import com.android.dialer.logging.ScreenEvent; import com.android.dialer.speeddial.SpeedDialFragment; +import com.android.dialer.util.PermissionsUtil; import com.android.dialer.voicemailstatus.VisualVoicemailEnabledChecker; import com.android.dialer.voicemailstatus.VoicemailStatusHelper; import java.util.ArrayList; @@ -76,6 +77,7 @@ public class ListsFragment extends Fragment private final ArrayList mOnPageChangeListeners = new ArrayList<>(); /** The position of the currently selected tab. */ private int mTabIndex = TAB_INDEX_SPEED_DIAL; + private boolean mPaused; private CallLogQueryHandler mCallLogQueryHandler; @@ -104,6 +106,8 @@ public class ListsFragment extends Fragment Trace.beginSection(TAG + " onResume"); super.onResume(); + mPaused = false; + if (getUserVisibleHint()) { sendScreenViewForCurrentPosition(); } @@ -127,6 +131,8 @@ public class ListsFragment extends Fragment ((CallLogFragment) mCurrentPage).onNotVisible(); } super.onPause(); + + mPaused = true; } @Override @@ -178,10 +184,15 @@ public class ListsFragment extends Fragment mRemoveView = (RemoveView) parentView.findViewById(R.id.remove_view); mRemoveViewContent = parentView.findViewById(R.id.remove_view_content); - getActivity() - .getContentResolver() - .registerContentObserver( - VoicemailContract.Status.CONTENT_URI, true, mVoicemailStatusObserver); + if (PermissionsUtil.hasReadVoicemailPermissions(getContext()) + && PermissionsUtil.hasAddVoicemailPermissions(getContext())) { + getActivity() + .getContentResolver() + .registerContentObserver( + VoicemailContract.Status.CONTENT_URI, true, mVoicemailStatusObserver); + } else { + LogUtil.w("ListsFragment.onCreateView", "no voicemail read/add permissions"); + } Trace.endSection(); Trace.endSection(); @@ -263,7 +274,7 @@ public class ListsFragment extends Fragment public void onVoicemailStatusFetched(Cursor statusCursor) { mHasFetchedVoicemailStatus = true; - if (getActivity() == null || getActivity().isFinishing()) { + if (getActivity() == null || mPaused) { return; } @@ -394,7 +405,7 @@ public class ListsFragment extends Fragment return; } - int screenType; + ScreenEvent.Type screenType; switch (getCurrentTabIndex()) { case TAB_INDEX_SPEED_DIAL: screenType = ScreenEvent.Type.SPEED_DIAL; diff --git a/java/com/android/dialer/app/list/OldSpeedDialFragment.java b/java/com/android/dialer/app/list/OldSpeedDialFragment.java index 4aafd9625782e6d65f72a6fb3dcf919fa58c505c..40fe745654ba9226fb04a1d17799a5f9f7940e01 100644 --- a/java/com/android/dialer/app/list/OldSpeedDialFragment.java +++ b/java/com/android/dialer/app/list/OldSpeedDialFragment.java @@ -51,8 +51,8 @@ import com.android.contacts.common.list.ContactTileView; import com.android.contacts.common.list.OnPhoneNumberPickerActionListener; import com.android.dialer.app.R; import com.android.dialer.app.widget.EmptyContentView; -import com.android.dialer.callintent.nano.CallInitiationType; -import com.android.dialer.callintent.nano.CallSpecificAppData; +import com.android.dialer.callintent.CallInitiationType; +import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.LogUtil; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.util.ViewUtil; @@ -123,7 +123,7 @@ public class OldSpeedDialFragment extends Fragment if (mContactTileAdapter != null) { mContactTileAdapter.refreshContactsPreferences(); } - if (PermissionsUtil.hasContactsPermissions(getActivity())) { + if (PermissionsUtil.hasContactsReadPermissions(getActivity())) { if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) { getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); @@ -235,7 +235,7 @@ public class OldSpeedDialFragment extends Fragment // Use initLoader() instead of restartLoader() to refraining unnecessary reload. // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will // be called, on which we'll check if "all" contacts should be reloaded again or not. - if (PermissionsUtil.hasContactsPermissions(activity)) { + if (PermissionsUtil.hasContactsReadPermissions(activity)) { getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); } else { setEmptyViewVisibility(true); @@ -462,8 +462,10 @@ public class OldSpeedDialFragment extends Fragment @Override public void onContactSelected(Uri contactUri, Rect targetRect) { if (mPhoneNumberPickerActionListener != null) { - CallSpecificAppData callSpecificAppData = new CallSpecificAppData(); - callSpecificAppData.callInitiationType = CallInitiationType.Type.SPEED_DIAL; + CallSpecificAppData callSpecificAppData = + CallSpecificAppData.newBuilder() + .setCallInitiationType(CallInitiationType.Type.SPEED_DIAL) + .build(); mPhoneNumberPickerActionListener.onPickDataUri( contactUri, false /* isVideoCall */, callSpecificAppData); } @@ -472,8 +474,10 @@ public class OldSpeedDialFragment extends Fragment @Override public void onCallNumberDirectly(String phoneNumber) { if (mPhoneNumberPickerActionListener != null) { - CallSpecificAppData callSpecificAppData = new CallSpecificAppData(); - callSpecificAppData.callInitiationType = CallInitiationType.Type.SPEED_DIAL; + CallSpecificAppData callSpecificAppData = + CallSpecificAppData.newBuilder() + .setCallInitiationType(CallInitiationType.Type.SPEED_DIAL) + .build(); mPhoneNumberPickerActionListener.onPickPhoneNumber( phoneNumber, false /* isVideoCall */, callSpecificAppData); } diff --git a/java/com/android/dialer/app/list/RegularSearchFragment.java b/java/com/android/dialer/app/list/RegularSearchFragment.java index 26959539bb7aebe58604702307eb1ce056e2285a..02896793b2c2952a2e4073b4e34ea0cce39d1b41 100644 --- a/java/com/android/dialer/app/list/RegularSearchFragment.java +++ b/java/com/android/dialer/app/list/RegularSearchFragment.java @@ -27,7 +27,7 @@ import com.android.contacts.common.list.PinnedHeaderListView; import com.android.dialer.app.R; import com.android.dialer.app.widget.EmptyContentView; import com.android.dialer.app.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; -import com.android.dialer.callintent.nano.CallInitiationType; +import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.phonenumbercache.CachedNumberLookupService; import com.android.dialer.phonenumbercache.PhoneNumberCache; import com.android.dialer.util.PermissionsUtil; @@ -133,7 +133,7 @@ public class RegularSearchFragment extends SearchFragment } @Override - protected int getCallInitiationType(boolean isRemoteDirectory) { + protected CallInitiationType.Type getCallInitiationType(boolean isRemoteDirectory) { return isRemoteDirectory ? CallInitiationType.Type.REMOTE_DIRECTORY : CallInitiationType.Type.REGULAR_SEARCH; diff --git a/java/com/android/dialer/app/list/SearchFragment.java b/java/com/android/dialer/app/list/SearchFragment.java index 4128300df868c143e21f360720b17c5ad40431a4..fcf8236e30536dfa94b008c200bde0862bc97999 100644 --- a/java/com/android/dialer/app/list/SearchFragment.java +++ b/java/com/android/dialer/app/list/SearchFragment.java @@ -42,7 +42,7 @@ import com.android.dialer.app.R; import com.android.dialer.app.dialpad.DialpadFragment.ErrorDialogFragment; import com.android.dialer.app.widget.DialpadSearchEmptyContentView; import com.android.dialer.app.widget.EmptyContentView; -import com.android.dialer.callintent.nano.CallSpecificAppData; +import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.LogUtil; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.IntentUtil; @@ -238,12 +238,13 @@ public class SearchFragment extends PhoneNumberPickerFragment { number = adapter.getQueryString(); listener = getOnPhoneNumberPickerListener(); if (listener != null && !checkForProhibitedPhoneNumber(number)) { - CallSpecificAppData callSpecificAppData = new CallSpecificAppData(); - callSpecificAppData.callInitiationType = - getCallInitiationType(false /* isRemoteDirectory */); - callSpecificAppData.positionOfSelectedSearchResult = position; - callSpecificAppData.charactersInSearchString = - getQueryString() == null ? 0 : getQueryString().length(); + CallSpecificAppData callSpecificAppData = + CallSpecificAppData.newBuilder() + .setCallInitiationType(getCallInitiationType(false /* isRemoteDirectory */)) + .setPositionOfSelectedSearchResult(position) + .setCharactersInSearchString( + getQueryString() == null ? 0 : getQueryString().length()) + .build(); listener.onPickPhoneNumber(number, false /* isVideoCall */, callSpecificAppData); } break; @@ -274,12 +275,13 @@ public class SearchFragment extends PhoneNumberPickerFragment { TextUtils.isEmpty(mAddToContactNumber) ? adapter.getQueryString() : mAddToContactNumber; listener = getOnPhoneNumberPickerListener(); if (listener != null && !checkForProhibitedPhoneNumber(number)) { - CallSpecificAppData callSpecificAppData = new CallSpecificAppData(); - callSpecificAppData.callInitiationType = - getCallInitiationType(false /* isRemoteDirectory */); - callSpecificAppData.positionOfSelectedSearchResult = position; - callSpecificAppData.charactersInSearchString = - getQueryString() == null ? 0 : getQueryString().length(); + CallSpecificAppData callSpecificAppData = + CallSpecificAppData.newBuilder() + .setCallInitiationType(getCallInitiationType(false /* isRemoteDirectory */)) + .setPositionOfSelectedSearchResult(position) + .setCharactersInSearchString( + getQueryString() == null ? 0 : getQueryString().length()) + .build(); listener.onPickPhoneNumber(number, true /* isVideoCall */, callSpecificAppData); } break; @@ -378,7 +380,7 @@ public class SearchFragment extends PhoneNumberPickerFragment { return; } - if (PermissionsUtil.hasContactsPermissions(getActivity())) { + if (PermissionsUtil.hasContactsReadPermissions(getActivity())) { super.startLoading(); } else if (TextUtils.isEmpty(getQueryString())) { // Clear out any existing call shortcuts. diff --git a/java/com/android/dialer/app/list/SmartDialSearchFragment.java b/java/com/android/dialer/app/list/SmartDialSearchFragment.java index c783d3ac36764515f8642e68aae8327d6457216f..eb1508c7287169346c448534e2ffb0fc7fc6b8bf 100644 --- a/java/com/android/dialer/app/list/SmartDialSearchFragment.java +++ b/java/com/android/dialer/app/list/SmartDialSearchFragment.java @@ -18,6 +18,10 @@ package com.android.dialer.app.list; import static android.Manifest.permission.CALL_PHONE; import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; @@ -26,7 +30,9 @@ import com.android.contacts.common.list.ContactEntryListAdapter; import com.android.dialer.app.R; import com.android.dialer.app.dialpad.SmartDialCursorLoader; import com.android.dialer.app.widget.EmptyContentView; -import com.android.dialer.callintent.nano.CallInitiationType; +import com.android.dialer.callintent.CallInitiationType; +import com.android.dialer.common.LogUtil; +import com.android.dialer.database.DialerDatabaseHelper; import com.android.dialer.util.PermissionsUtil; /** Implements a fragment to load and display SmartDial search results. */ @@ -34,10 +40,17 @@ public class SmartDialSearchFragment extends SearchFragment implements EmptyContentView.OnEmptyViewActionButtonClickedListener, FragmentCompat.OnRequestPermissionsResultCallback { - private static final String TAG = SmartDialSearchFragment.class.getSimpleName(); - private static final int CALL_PHONE_PERMISSION_REQUEST_CODE = 1; + private final BroadcastReceiver mSmartDialUpdatedReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + LogUtil.i("SmartDialSearchFragment.onReceive", "smart dial update broadcast received"); + reloadData(); + } + }; + /** Creates a SmartDialListAdapter to display and operate on search results. */ @Override protected ContactEntryListAdapter createListAdapter() { @@ -82,6 +95,27 @@ public class SmartDialSearchFragment extends SearchFragment } } + @Override + public void onStart() { + super.onStart(); + + LogUtil.i("SmartDialSearchFragment.onStart", "registering smart dial update receiver"); + + getActivity() + .registerReceiver( + mSmartDialUpdatedReceiver, + new IntentFilter(DialerDatabaseHelper.ACTION_SMART_DIAL_UPDATED)); + } + + @Override + public void onStop() { + super.onStop(); + + LogUtil.i("SmartDialSearchFragment.onStop", "unregistering smart dial update receiver"); + + getActivity().unregisterReceiver(mSmartDialUpdatedReceiver); + } + @Override public void onEmptyViewActionButtonClicked() { final Activity activity = getActivity(); @@ -102,7 +136,7 @@ public class SmartDialSearchFragment extends SearchFragment } @Override - protected int getCallInitiationType(boolean isRemoteDirectory) { + protected CallInitiationType.Type getCallInitiationType(boolean isRemoteDirectory) { return CallInitiationType.Type.SMART_DIAL; } diff --git a/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml b/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml index 7e450c4cd976ff2a07e05cf60a2bd4e3ed811aa7..ca93da0deb249250f185e79d7e41c16bff9383c3 100644 --- a/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml +++ b/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml @@ -112,6 +112,11 @@ android:resource="@layout/keyguard_preview"/> + + diff --git a/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png b/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png new file mode 100644 index 0000000000000000000000000000000000000000..d6f6daaab2a3ef4811850c7d5488565dcb118fc2 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/empty_contacts.png b/java/com/android/dialer/app/res/drawable-hdpi/empty_contacts.png new file mode 100644 index 0000000000000000000000000000000000000000..d3c0378f52890dd9f04dde5b55966e797fc50379 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/empty_contacts.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/empty_speed_dial.png b/java/com/android/dialer/app/res/drawable-hdpi/empty_speed_dial.png new file mode 100644 index 0000000000000000000000000000000000000000..3e9232fc95aec42a2ce2cb6a1d8c2d4c70e09145 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/empty_speed_dial.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_archive_white_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_archive_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..bb72e890f6e7d5cd20a2cafed46c1fc12e9e3763 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_archive_white_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_content_copy_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_content_copy_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..70eb0737882e53ec326b7a37cf335fea48f7b605 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_content_copy_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_delete_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_delete_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..9fb43b066e09b7f7b58672aec7dc806a70d77e32 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_delete_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_add_call.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_add_call.png new file mode 100644 index 0000000000000000000000000000000000000000..4e0d5649eb6dace9984eea36247e4357eb25fa70 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_add_call.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_current_call.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_current_call.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf41d5984c6d95601ff9de38040e1d8165ad6c4 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_current_call.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png new file mode 100644 index 0000000000000000000000000000000000000000..043685fd9392e537c3a514aa54ced14f25c1268c Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_grade_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_grade_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..86eecdd4a0a40e1fe48095fd5262398828101f17 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_grade_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_handle.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..34310aa49328f2340a3931b9f8bbdb61a9461fd5 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_handle.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..a36323ca93a238ea8fdb04b59095f960ec1e7659 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png new file mode 100644 index 0000000000000000000000000000000000000000..4b67cf71a29077360cb63539e3a43254b7698490 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_more_vert_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_more_vert_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..67f07e473442d1f5bd5dc486a42ce4bedf40b425 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_more_vert_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..26a26f911dec234fd2704e72798bdae0236adf1b Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png new file mode 100644 index 0000000000000000000000000000000000000000..bf413f9122c095517884ab0e3ca46775f5c4b8bf Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_pause_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_pause_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..4d2ea05c462291e4a4f8bd30856a25ad33fd420f Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_pause_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_people_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_people_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..ff698afc0f44ec4628bb0b9dd60af34ae62863e6 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_people_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b27dfba06ecd1148c01ef456f1567299a21095af Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_play_arrow_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_play_arrow_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..57c9fa5460323823edb0289c1d15f0f561e0c06e Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_play_arrow_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee6adf8d54a555e114a04695f62524ae4203ab4 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_results_phone.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_results_phone.png new file mode 100644 index 0000000000000000000000000000000000000000..3a1a7a7905b8ced6c9e6ae6f359515116a1a672e Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_results_phone.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_schedule_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_schedule_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..f3581d1040bbd0fee132725875427590cf5e8462 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_schedule_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_share_white_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_share_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b09a6926de5aa48dee59265aadac32da236f9e1c Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_share_white_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png new file mode 100644 index 0000000000000000000000000000000000000000..62e1f8a6d629588975e1f19199a63cc0f58e96b4 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png new file mode 100644 index 0000000000000000000000000000000000000000..03643b20d64b04f8e622a44c523a1625608ec423 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_off_dis.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_off_dis.png new file mode 100644 index 0000000000000000000000000000000000000000..47e32492c783ea88192e55fb5665beae1774563f Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_off_dis.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_off_dk.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_off_dk.png new file mode 100644 index 0000000000000000000000000000000000000000..2bfe0c0cf35151a445ec0de7bf9d651f5543a45e Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_off_dk.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_on_dis.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_on_dis.png new file mode 100644 index 0000000000000000000000000000000000000000..90b5238f3bf497d1a704280c9e0f606e269143bf Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_on_dis.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_on_dk.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_on_dk.png new file mode 100644 index 0000000000000000000000000000000000000000..7556637fce7f6b33a461d8986538dca3ceda7eb5 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_vm_sound_on_dk.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_voicemail_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_voicemail_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..03a62e15f90fc0cbfc0d743228e74a8ab242c781 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_voicemail_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_volume_down_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_volume_down_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..e22e92c857e07a0142f8fc6ae0edc715e8658594 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_volume_down_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_volume_up_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_volume_up_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..57d787163e90cc34c16eca4e924adca106deb12c Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/ic_volume_up_24dp.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png b/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png new file mode 100644 index 0000000000000000000000000000000000000000..3dc1c17f613473140b70a66c58a73bbff674a2b1 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png differ diff --git a/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png b/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png new file mode 100644 index 0000000000000000000000000000000000000000..44b06f26166f5106823a8d8a6f379f17c76e56b8 Binary files /dev/null and b/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png differ diff --git a/java/com/android/dialer/app/res/layout/all_contacts_fragment.xml b/java/com/android/dialer/app/res/layout/all_contacts_fragment.xml index f59847825ec1958f236aa90af2f32b8c4da42ee8..17a45208d9ad9bd751d697bd7853f90f3e22ad32 100644 --- a/java/com/android/dialer/app/res/layout/all_contacts_fragment.xml +++ b/java/com/android/dialer/app/res/layout/all_contacts_fragment.xml @@ -41,7 +41,9 @@ android:paddingTop="18dp" android:fadingEdge="none" android:fastScrollEnabled="true" - android:nestedScrollingEnabled="true"/> + android:nestedScrollingEnabled="true" + android:cropToPadding="false" + android:clipToPadding="false"/> + android:src="@drawable/ic_call_and_share"/> + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/contact_tile" + class="com.android.dialer.app.list.PhoneFavoriteSquareTileView" + android:paddingBottom="@dimen/contact_tile_divider_width" + android:paddingEnd="@dimen/contact_tile_divider_width"> - - + android:focusable="true" + android:nextFocusRight="@+id/contact_tile_secondary_button"> + + - + android:layout_height="match_parent" + android:orientation="vertical"> + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="6"/> + - - + android:layout_alignParentBottom="true" + android:paddingBottom="@dimen/contact_tile_text_bottom_padding" + android:paddingStart="@dimen/contact_tile_text_side_padding" + android:paddingEnd="@dimen/contact_tile_text_side_padding" + android:orientation="vertical"> + + + + + - - - + android:textSize="11sp"/> + android:id="@+id/contact_tile_push_state" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/item_background_material_dark" + android:importantForAccessibility="no"/> + + + + - + diff --git a/java/com/android/dialer/app/res/layout/search_edittext.xml b/java/com/android/dialer/app/res/layout/search_edittext.xml index 903fbcae94913005356838bfd91b3aed9b0d12fa..c02512d8086e21faf17ae4a8777ad4f67abe7188 100644 --- a/java/com/android/dialer/app/res/layout/search_edittext.xml +++ b/java/com/android/dialer/app/res/layout/search_edittext.xml @@ -10,12 +10,14 @@ android:layout_marginRight="@dimen/search_margin_horizontal" android:background="@drawable/rounded_corner" android:elevation="@dimen/search_box_elevation" + android:theme="@style/DialtactsSearchBarThemeOverlay" android:orientation="horizontal"> diff --git a/java/com/android/dialer/app/res/menu/actionbar_delete.xml b/java/com/android/dialer/app/res/menu/actionbar_delete.xml index 10e53494175f2c7e10cc861e0e75c7c7891c7706..b8aa3813b1c52b5e0a8777053c9395076b2012a9 100644 --- a/java/com/android/dialer/app/res/menu/actionbar_delete.xml +++ b/java/com/android/dialer/app/res/menu/actionbar_delete.xml @@ -18,7 +18,7 @@

diff --git a/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png b/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png new file mode 100644 index 0000000000000000000000000000000000000000..15c41423bede3f5773389254af6aa92dfa638e87 Binary files /dev/null and b/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png differ diff --git a/java/com/android/dialer/app/res/values-af/strings.xml b/java/com/android/dialer/app/res/values-af/strings.xml index 6188a598357495e026bbb0e0e446e867028b86bc..7eaa7cb943406d5589e9617913ccf72b03667b0d 100644 --- a/java/com/android/dialer/app/res/values-af/strings.xml +++ b/java/com/android/dialer/app/res/values-af/strings.xml @@ -42,6 +42,8 @@ "Bel terug" "Boodskap" "%1$s: %2$s" + "Bel %s" + "Stemboodskapnommer onbekend" %1$d Stemboodskappe Stemboodskap @@ -97,6 +99,11 @@ "Stemboodskap" "%s sek." "%s min. %s sek." + "stemboodskap" + "stemboodskappe" + "Ja" + "Nee" + "Vee geselekteerde %1$s uit?" @string/call_log_header_today "%1$s om %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Oproepe" "Oproepblokkering" "Stemboodskap" + + "Oproepblokkering is tydelik af" "Oproepblokkering is gedeaktiveer omdat jy die afgelope 48 uur nooddienste van hierdie foon af gekontak het. Dit sal outomaties heraktiveer word sodra die 48-uurtydperk verstryk." "Voer nommers in" @@ -221,4 +230,6 @@ "Deblokkeer nommer" "Strooipos" "%1$s is vanlyn en kan nie bereik word nie" + + diff --git a/java/com/android/dialer/app/res/values-am/strings.xml b/java/com/android/dialer/app/res/values-am/strings.xml index 228fe94c68951359209ced0fe61975494d5988c7..dd20b3119231d7e24fecf1c23bb48ac5307cd709 100644 --- a/java/com/android/dialer/app/res/values-am/strings.xml +++ b/java/com/android/dialer/app/res/values-am/strings.xml @@ -42,6 +42,8 @@ "መልሰህ ደውል" "መልእክት" "%1$s:%2$s" + "%s ይደውሉ" + "የማይታወቅ የድምፅ መልዕክት ቁጥር" %1$d የድምፅ መልዕክቶች %1$d የድምፅ መልዕክቶች @@ -97,6 +99,12 @@ "የድምፅ መልዕክት" "%s ሰከንድ" "%s ደቂቃ %s ሴከ" + "የድምፅ መልዕክት" + "የድምፅ መልዕክቶች" + "አዎ" + "አይ" + + @string/call_log_header_today "%1$s %2$s ላይ" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "ጥሪዎች" "ጥሪን ማገድ" "የድምፅ መልእክት" + + "ጥሪን ማገድ ለጊዜው ተሰናክሏል" "ባለፉት 48 ሰዓቶች ውስጥ ከዚህ ስልክ ሆነው የአስቸኳይ አደጋ አገልግሎቶችን ስላነጋገሩ ጥሪን ማገድ ተሰናክሏል። አንዴ የ48 ሰዓቱ ጊዜ ካለፈ በኋላ በራስ-ሰር ዳግም ይነቃል።" "ቁጥሮችን አስመጣ" @@ -221,4 +231,6 @@ "ቁጥርን አታግድ" "አይፈለጌ መልዕክት" "%1$s ከመስመር ውጭ ነው እና ሊደረስበት አይችልም" + + diff --git a/java/com/android/dialer/app/res/values-ar/strings.xml b/java/com/android/dialer/app/res/values-ar/strings.xml index 2d9c7e8e0e8812646167c96c4b9ff7cb0b45c65c..c24d313c430ba217512a2bcf110bbdef6d3c0e14 100644 --- a/java/com/android/dialer/app/res/values-ar/strings.xml +++ b/java/com/android/dialer/app/res/values-ar/strings.xml @@ -42,6 +42,8 @@ "معاودة الاتصال" "رسالة" "%1$s: %2$s" + "طلب %s" + "رقم البريد الصوتي غير معروف" لا تتوفر رسائل بريد صوتي (%1$d) رسالتا بريد صوتي (%1$d) @@ -101,6 +103,11 @@ "البريد الصوتي" "%s ثانية" "%s دقيقة %s ثانية" + "البريد الصوتي" + "رسائل البريد الصوتي" + "نعم" + "لا" + "حذف رسائل %1$s المحددة؟" @string/call_log_header_today "%1$s في %2$s" "%1$02d:%2$02d" @@ -200,6 +207,8 @@ "المكالمات" "حظر المكالمات" "البريد الصوتي" + + "حظر المكالمات معطّل مؤقتًا" "تم تعطيل حظر المكالمات لأنك اتصلت بخدمات الطوارئ خلال 48 ساعة ماضية. وستتم إعادة تمكينه تلقائيًا بعد انتهاء هذه الفترة التي تبلغ 48 ساعة." "استيراد الأرقام" @@ -229,4 +238,6 @@ "إلغاء حظر الرقم" "تعليق غير مرغوب فيه" "%1$s غير متصل ولا يمكن الوصول إليه" + + diff --git a/java/com/android/dialer/app/res/values-az/strings.xml b/java/com/android/dialer/app/res/values-az/strings.xml index e2e9bea50ef7e8c66fc6aaf3dc9a6de37fc47beb..70e926cbefb7204f8bca83920092972930e8103b 100644 --- a/java/com/android/dialer/app/res/values-az/strings.xml +++ b/java/com/android/dialer/app/res/values-az/strings.xml @@ -42,6 +42,8 @@ "Geriyə zəng" "Mesaj" "%1$s: %2$s" + "%s nömrəsini yığın" + "Səsli e-poçt nömrəsi naməlumdur" %1$d Səsli poçt Səsli poçt @@ -97,6 +99,12 @@ "Səsli poçt" "%s san" "%s dəq %s san" + "səsli e-məktub" + "səsli e-məktublar" + "Bəli" + "Xeyr" + + @string/call_log_header_today "%1$s tarixində %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Zənglər" "Zəng blok edilir" "Səsli e-məktub" + + "Çağrının blok edilməsi müvəqqəti olaraq deaktiv edilib" "Son 48 saat ərzində bu telefondan təcili yardım xidmətləri ilə əlaqə saxladığınız üçün Çağrı Bloklanması deaktiv edildi. 48 saatlıq müddət başa çatdıqda avtomatik olaraq yenidən aktiv ediləcək." "Nömrələri import edin" @@ -221,4 +231,6 @@ "Nömrəni blokdan çıxarın" "Spam" "%1$s oflayn olduğu üçün əlaqə saxlamaq mümkün deyil" + + diff --git a/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml b/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..7ca2e56ec04cc11dba7ebf7e0f4f89cdcbf2a35f --- /dev/null +++ b/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,238 @@ + + + + + "Telefon" + "Telefonska tastatura" + "Telefon" + "Istorija poziva" + "Prijavi netačan broj" + "Kopiraj broj" + "Kopiraj transkripciju" + "Blokiraj broj" + "Deblokiraj broj" + "Izmeni broj pre poziva" + "Obriši istoriju poziva" + "Izbriši govornu poruku" + "Gov. pošta je izbrisana" + "OPOZOVI" + "Želite da obrišete istoriju poziva?" + "Ovo će izbrisati sve pozive iz istorije" + "Briše se istorija poziva…" + "Telefon" + "Propušten poziv" + "Propušten poziv za Work" + "Propušteni pozivi" + "Broj propuštenih poziva: %d" + "Uzvrati poziv" + "Pošalji SMS" + "%1$s: %2$s" + "Pozovi %s" + "Nepoznat broj govorne pošte" + + %1$d govorna poruka + %1$d govorne poruke + %1$d govornih poruka + + "Pusti" + "%1$s, %2$s" + "Nova govorna poruka od %1$s" + "Puštanje govorne pošte nije uspelo" + "Govorna pošta se učitava…" + "Govorna pošta se arhivira…" + "Učitavanje govorne pošte nije uspelo" + "Samo pozivi sa govornom poštom" + "Samo dolazni pozivi" + "Samo odlazni pozivi" + "Samo propušteni pozivi" + "(%1$d) %2$s" + "pretraži" + "biranje" + "broj za biranje" + "Pokretanje ili zaustavljanje reprodukcije" + "Uključivanje ili isključivanje spikerfona" + "Traženje pozicije u reprodukciji" + "Smanjivanje brzine reprodukcije" + "Povećavanje brzine reprodukcije" + "Istorija poziva" + "Još opcija" + "tastatura" + "Prikaži samo odlazne" + "Prikaži samo dolazne" + "Prikaži samo propuštene" + "Prikaži samo govorne poruke" + "Prikaži sve pozive" + "Dodaj pauzu od 2 sekunde" + "Dodaj čekanje" + "Podešavanja" + "Simulator" + "Svi kontakti" + "Upotrebite brojčanik za tonsko biranje" + "Vrati se na poziv koji je u toku" + "Dodaj poziv" + "Dolazni pozivi" + "Puštanje govorne pošte" + "Prikaži kontakt %1$s" + "Pozovi %1$s" + "Detalji o kontaktu za %1$s" + "Kontakt informacije potencijalnog nepoželjnog pozivaoca %1$s" + "%1$s poziva." + "Video poziv." + "Slanje SMS-a za %1$s" + "Nepreslušana govorna pošta" + "Pokretanje glasovne pretrage" + "Pozovi %s" + "Govorna pošta" + "%s sek" + "%s min %s sek" + "govornu poruku" + "govorne poruke" + "Da" + "Ne" + + + @string/call_log_header_today + "%1$s u %2$s" + "%1$02d:%2$02d" + "%1$s%2$s" + "Nije moguće pozvati ovaj broj" + "Da biste podesili govornu poštu, idite u Meni > Podešavanja." + "Da biste pozvali govornu poštu, prvo isključite režim rada u avionu." + "Učitava se…" + "IMEI" + "MEID" + "Učitava se sa SIM kartice…" + "Kontakti na SIM kartici" + "Nema dostupne aplikacije za kontakte" + "Glasovna pretraga nije dostupna" + "Nije moguće uputiti telefonski poziv jer je aplikacija Telefon onemogućena." + "Pretraži kontakte" + "Dodajte broj ili pretražite kontakte" + "Istorija poziva je prazna" + "Pozovi" + "Nemate nijedan propušten poziv." + "Prijemno sanduče govorne pošte je prazno." + "Prikaži samo omiljene" + "Istorija poziva" + "Svi" + "Propušteni" + "Govorna pošta" + "Brzo biranje" + "Istorija poziva" + "Kontakti" + "Govorna pošta" + "Uklonjeno je iz omiljenih" + "Opozovi" + "Pozovi %s" + "Napravi novi kontakt" + "Dodaj u kontakt" + "Pošalji SMS" + "Uputi video poziv" + "Blokiraj broj" + "Novih propuštenih poziva: %s" + "Nemate nijedan kontakt na brzom biranju" + "Dodaj omiljen kontakt" + "Još uvek nemate nijedan kontakt" + "Dodaj kontakt" + "Dodirnite sliku da biste videli sve brojeve ili dodirnite i zadržite da biste im promenili raspored" + "Ukloni" + "Video poziv" + "Pošalji poruku" + "Detalji poziva" + "Pošalji u…" + "Pozovi ^1" + "Propušteni poziv: ^1, ^2, ^3, ^4." + "Primljeni poziv: ^1, ^2, ^3, ^4." + "Nepročitana govorna poruka od ^1, ^2, ^3, ^4." + "Govorna poruka od ^1, ^2, ^3, ^4." + "Pozvali ste: ^1, ^2, ^3, ^4." + "preko %1$s" + "%1$s preko %2$s" + "Pozovi ^1" + "Uputite video poziv kontaktu ^1." + "Pusti govornu poštu od ^1" + "Reprodukuj govornu poštu kontakta ^1" + "Pauziraj govornu poštu kontakta ^1" + "Izbriši govornu poštu kontakta ^1" + + %d nova poruka govorne pošte + %d nove poruke govorne pošte + %d novih poruka govorne pošte + + "Napravite kontakt za ^1" + "Dodajte ^1 postojećem kontaktu" + "Detalji poziva za ^1" + "Izbrisano iz istorije poziva" + "Danas" + "Juče" + "Stariji" + "Lista poziva" + "Uključite zvučnik." + "Isključite zvučnik." + "Brža reprodukcija." + "Sporija reprodukcija." + "Započnite ili pauzirajte reprodukciju." + "Opcije prikaza" + "Zvuci i vibracija" + "Pristupačnost" + "Zvuk zvona telefona" + "Vibriraj i za pozive" + "Tonovi tastature" + "Dužina trajanja tona tastature" + + "Normalno" + "Dugačak" + + "Brzi odgovori" + "Pozivi" + "Blokiranje poziva" + "Govorna pošta" + + + "Blokiranje poziva je privremeno isključeno" + "Blokiranje poziva je onemogućeno zato što ste kontaktirali službe za pomoć u hitnim slučajevima sa ovog telefona u poslednjih 48 sati. Automatski će biti ponovo omogućeno kada istekne period od 48 sati." + "Uvezi brojeve" + "Ranije ste označili neke pozivaoce koje automatski treba preusmeriti na govornu poštu preko drugih aplikacija." + "Prikaži brojeve" + "Uvezi" + "Deblokiraj broj" + "Dodaj broj" + "Pozivi sa ovih brojeva će biti blokirani i poruke govorne pošte će se automatski brisati." + "Pozivi sa ovih brojeva će biti blokirani, ali pozivaoci sa ovih brojeva će i dalje moći da vam ostavljaju poruke govorne pošte." + "Blokirani brojevi" + "%1$s je već blokiran." + "Nalozi za pozivanje" + "Uključi" + "Podesi dozvole" + "Da biste omogućili brzo biranje, uključite dozvolu za Kontakte." + "Da biste videli evidenciju poziva, uključite dozvolu za Telefon." + "Da biste videli kontakte, uključite dozvolu za Kontakte." + "Da biste pristupili govornoj pošti, uključite dozvolu za Telefon." + "Da biste pretražili kontakte, uključite dozvole za Kontakte." + "Da biste uputili poziv, uključite dozvolu za Telefon." + "Aplikacija Telefon nema dozvolu za upisivanje u sistemska podešavanja." + "Blokirano" + "Blokiraj/prijavi kao nepoželjan" + "Blokiraj broj" + "Nije nepoželjan" + "Deblokiraj broj" + "Nepoželjan" + "%1$s je oflajn i ne možete da ga/je kontaktirate" + + + diff --git a/java/com/android/dialer/app/res/values-be/strings.xml b/java/com/android/dialer/app/res/values-be/strings.xml index 337a6261743b452346f3517db84e0850c637566a..effc7e02522eb897bf62caf493bb7c4cfdf65aa2 100644 --- a/java/com/android/dialer/app/res/values-be/strings.xml +++ b/java/com/android/dialer/app/res/values-be/strings.xml @@ -42,6 +42,8 @@ "Адказаць" "Паведамленне" "%1$s: %2$s" + "Набраць %s" + "Невядомы нумар галасавой пошты" %1$d Паведамленне галасавой пошты %1$d Паведамленні галасавой пошты @@ -99,6 +101,12 @@ "Галасавая пошта" "%s с" "%s хв %s с" + "галасавая пошта" + "галасавая пошта" + "Так" + "Не" + + @string/call_log_header_today "%1$s у %2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Выклікі" "Блакіраванне выклікаў" "Галасавая пошта" + + "Блакіроўка выклікаў часова адключана" "Блакіроўка выклікаў будзе адключана, таму што вы выклікалі экстранныя службы з гэтага тэлефона на працягу апошніх 48 гадзін. Яна будзе аўтаматычна адноўлена пасля заканчэння перыяду ў 48 гадзін." "Імпартаваць нумары" @@ -225,4 +235,6 @@ "Разблакіраваць нумар" "Спам" "Карыстальнік %1$s па-за сеткай і не даступны" + + diff --git a/java/com/android/dialer/app/res/values-bg/strings.xml b/java/com/android/dialer/app/res/values-bg/strings.xml index 510b4a2d0a025e22baae2cdc167e20768d124164..d3d1a99742fc1ab3049d9ed1953e8c9f31ea57ba 100644 --- a/java/com/android/dialer/app/res/values-bg/strings.xml +++ b/java/com/android/dialer/app/res/values-bg/strings.xml @@ -42,6 +42,8 @@ "Обратно обаждане" "Съобщение" "%1$s: %2$s" + "Набиране на %s" + "Неизвестен номер за гласова поща" %1$d гласови съобщения Гласово съобщение @@ -97,6 +99,11 @@ "Гласова поща" "%s сек" "%s мин %s сек" + "гласово съобщение" + "гласови съобщения" + "Да" + "Не" + "Избрахте %1$s – да се изтрие ли избраното?" @string/call_log_header_today "%1$s в %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Обаждания" "Блокиране на обажданията" "Гласова поща" + + "Блокир. на обажданията е временно изкл." "Блокирането на обажданията е деактивирано, защото в рамките на последните 48 часа сте се свързали със спешните служби от този телефон. То автоматично ще бъде активирано отново, когато периодът от 48 часа изтече." "Импортиране на номерата" @@ -221,4 +230,6 @@ "Отблокиране на номера" "Спам" %1$s не може да се установи връзка, тъй като е офлайн" + + diff --git a/java/com/android/dialer/app/res/values-bn/strings.xml b/java/com/android/dialer/app/res/values-bn/strings.xml index ece833ce7647506623ef5117bd20b303cb0bc20d..4b7354c007e32e9d6766ea21ed8791cc3c67697a 100644 --- a/java/com/android/dialer/app/res/values-bn/strings.xml +++ b/java/com/android/dialer/app/res/values-bn/strings.xml @@ -42,6 +42,8 @@ "কল ব্যাক করুন" "বার্তা" "%1$s: %2$s" + "%s এ ডায়াল করুন" + "ভয়েসমেল নম্বর অজানা" %1$dটি ভয়েসমেল %1$dটি ভয়েসমেল @@ -97,6 +99,12 @@ "ভয়েসমেল" "%s সেকেন্ড" "%s মিনিট %s সেকেন্ড" + "ভয়েসমেল" + "ভয়েসমেলগুলি" + "হ্যাঁ" + "না" + + @string/call_log_header_today "%1$s তারিখে %2$s\'টায়" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "কল" "কল অবরোধ করা" "ভয়েসমেল" + + "কল অবরোধ সাময়িকভাবে বন্ধ রয়েছে" "কল অবরোধ অক্ষম করা হয়েছে কারণ আপনি গত ২৮ ঘন্টার মধ্যে এই ফোন থেকে জরুরি পরিষেবায় যোগাযোগ করেছেন। ২৮ ঘন্টার সময়সীমা পেরিয়ে গেলেই এটি স্বয়ংক্রিয়ভাবে আবার সক্ষম হবে।" "নম্বরগুলি আমদানি করুন" @@ -221,4 +231,6 @@ "নম্বর অবরোধ মুক্ত করুন" "স্প্যাম" "%1$s এখন অফলাইনে থাকায় যোগাযোগ করা যাবে না" + + diff --git a/java/com/android/dialer/app/res/values-bs/strings.xml b/java/com/android/dialer/app/res/values-bs/strings.xml index 98506dc45215d8752942ab32fe191ad901cc4a46..4e028461aa758495ffda20709835b69be4fd3912 100644 --- a/java/com/android/dialer/app/res/values-bs/strings.xml +++ b/java/com/android/dialer/app/res/values-bs/strings.xml @@ -42,6 +42,8 @@ "Povr. poziv" "Poruka" "%1$s: %2$s" + "Pozovi %s" + "Nepoznat broj govorne pošte" %1$d Poruka govorne pošte %1$d Poruke govorne pošte @@ -98,6 +100,12 @@ "Govorna pošta" "%s sek." "%s min. %s sek." + "poruka govorne pošte" + "poruke govorne pošte" + "Da" + "Ne" + + @string/call_log_header_today "%1$s u %2$s" "%1$02d:%2$02d" @@ -194,6 +202,8 @@ "Pozivi" "Blokiranje poziva" "Govorna pošta" + + "Blokiranje poziva je privremeno isključeno" "Blokiranje poziva je onemogućeno jer ste kontaktirali hitnu službu s ovog telefona u proteklih 48 sati. Automatski će se ponovo omogućiti kada istekne 48 sati." "Uvezi brojeve" @@ -223,4 +233,6 @@ "Deblokiraj broj" "Neželjena pošta" "Osoba %1$s je van mreže i ne možete je kontaktirati" + + diff --git a/java/com/android/dialer/app/res/values-ca/strings.xml b/java/com/android/dialer/app/res/values-ca/strings.xml index 781c6064e2b5b73b87c02d4e9f1332037f4a376c..e18256d5a4d772592b139c3943eef2fddac09b65 100644 --- a/java/com/android/dialer/app/res/values-ca/strings.xml +++ b/java/com/android/dialer/app/res/values-ca/strings.xml @@ -42,6 +42,8 @@ "Torna la trucada" "Missatge" "%1$s: %2$s" + "Marca el número %s" + "Número de la bústia de veu desconegut" %1$d bústies de veu Bústia de veu @@ -97,6 +99,12 @@ "Bústia de veu" "%s s" "%s min %s s" + "missatge de veu" + "missatges de veu" + "Sí" + "No" + + @string/call_log_header_today "%1$s a les %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Trucades" "Bloqueig de trucades" "Bústia de veu" + + "Bloqueig de trucades desactivat tempor." "El bloqueig de trucades s\'ha desactivat perquè has contactat amb els serveis d\'emergència des d\'aquest telèfon durant les últimes 48 hores. Es tornarà a activar automàticament una vegada transcorregut el període de 48 hores." "Importa els números" @@ -221,4 +231,6 @@ "Desbloqueja el número" "Contingut brossa" "%1$s no té connexió i no s\'hi pot contactar" + + diff --git a/java/com/android/dialer/app/res/values-cs/strings.xml b/java/com/android/dialer/app/res/values-cs/strings.xml index 4f35d9cffb814132ec24ad0d660e082185510027..bb7e3c5fb8e22cf00d7168348da6f13be094f906 100644 --- a/java/com/android/dialer/app/res/values-cs/strings.xml +++ b/java/com/android/dialer/app/res/values-cs/strings.xml @@ -42,6 +42,8 @@ "Zavolat zpět" "Zpráva" "%1$s: %2$s" + "Volat hlasovou schránku %s" + "Číslo hlasové schránky není známé" %1$d hlasové zprávy %1$d hlasové zprávy @@ -99,6 +101,12 @@ "Hlasová schránka" "%s s" "%s min %s s" + "vybranou hlasovou zprávu" + "vybrané hlasové zprávy" + "Ano" + "Ne" + + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Volání" "Blokování hovorů" "Hlasová schránka" + + "Blokování hovorů je dočasně vypnuto" "Protože jste z tohoto telefonu během posledních 48 hodin volali na tísňovou linku, bylo blokování hovorů vypnuto. Po uplynutí 48 hodin se automaticky znovu zapne." "Importovat čísla" @@ -225,4 +235,6 @@ "Zrušit blokování čísla" "Spam" "Uživatel %1$s je offline a není možné se s ním spojit" + + diff --git a/java/com/android/dialer/app/res/values-da/strings.xml b/java/com/android/dialer/app/res/values-da/strings.xml index c3d44c01f9e0f6280219191bb072f0bac8fe478d..49881765287a5edf395fd4d1243c0d169da5e902 100644 --- a/java/com/android/dialer/app/res/values-da/strings.xml +++ b/java/com/android/dialer/app/res/values-da/strings.xml @@ -42,6 +42,8 @@ "Ring tilbage" "Besked" "%1$s: %2$s" + "Ring til %s" + "Nummeret for talebeskeden er ukendt" %1$d talebeskeder %1$d talebeskeder @@ -97,6 +99,12 @@ "Telefonsvarer" "%s sek." "%s min. %s sek." + "talebesked" + "talebeskeder" + "Ja" + "Nej" + + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Opkald" "Opkaldsblokering" "Telefonsvarer" + + "Opkaldsblokering er midlertidigt slået fra" "Opkaldsblokering er blevet deaktiveret, da du inden for de sidste 48 timer har kontaktet en alarmcentral. Blokeringen aktiveres automatisk igen, når perioden på 48 timer er udløbet." "Importér numre" @@ -221,4 +231,6 @@ "Ophæv blokering af nummer" "Spam" "%1$s er offline og kan ikke nås" + + diff --git a/java/com/android/dialer/app/res/values-de/strings.xml b/java/com/android/dialer/app/res/values-de/strings.xml index 25bc8a6df1941db9df50a42604a0306656247389..ab12c1f4f0577b3d4c86cccbce4fc5400499ae95 100644 --- a/java/com/android/dialer/app/res/values-de/strings.xml +++ b/java/com/android/dialer/app/res/values-de/strings.xml @@ -42,6 +42,10 @@ "Zurückrufen" "Nachricht" "%1$s: %2$s" + + + + %1$d Mailboxnachrichten Mailboxnachricht @@ -97,6 +101,12 @@ "Mailbox" "%s s" "%s min %s s" + "Mailboxnachricht" + "Mailboxnachrichten" + "Ja" + "Nein" + + @string/call_log_header_today "%1$s um %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Anrufe" "Anrufblockierung" "Mailbox" + + "Anrufblockierung vorübergehend aus" "Die Anrufblockierung wurde deaktiviert, weil du innerhalb der letzten 48 Stunden mit diesem Telefon den Notruf gewählt hast. Nach Ablauf dieser 48-Stunden-Frist wird die Blockierung automatisch wieder aktiviert." "Nummern importieren" @@ -221,4 +233,6 @@ "Blockierung der Nummer aufheben" "Spam" "%1$s ist offline und nicht erreichbar" + + diff --git a/java/com/android/dialer/app/res/values-el/strings.xml b/java/com/android/dialer/app/res/values-el/strings.xml index 620ae1130d58f3a697dd22f5d275ecfb9ae938e3..2a00c46f79bc8c62e3f6df0e40a881fbe0305469 100644 --- a/java/com/android/dialer/app/res/values-el/strings.xml +++ b/java/com/android/dialer/app/res/values-el/strings.xml @@ -42,6 +42,8 @@ "Επανάκληση" "Μήνυμα" "%1$s: %2$s" + "Κλήση %s" + "Ο αριθμός αυτόματου τηλεφωνητή είναι άγνωστος" %1$d Μηνύματα αυτόμ. τηλεφωνητή Μήνυμα αυτόματου τηλεφωνητή @@ -97,6 +99,12 @@ "Αυτόματος τηλεφωνητής" "%s δευτερόλεπτα" "%s λεπτά %s δευτερόλεπτα" + "φωνητικού μηνύματος αυτόματου τηλεφωνητή" + "φωνητικών μηνυμάτων αυτόματου τηλεφωνητή" + "Ναι" + "Όχι" + + @string/call_log_header_today "%1$s στις %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Κλήσεις" "Φραγή κλήσεων" "Αυτόματος τηλεφωνητής" + + "Προσωρινά απενεργοποιημένη φραγή κλήσεων" "Η φραγή κλήσεων έχει απενεργοποιηθεί προσωρινά επειδή επικοινωνήσατε με τις υπηρεσίες έκτακτης ανάγκης από αυτό το τηλέφωνο μέσα στις τελευταίες 48 ώρες. Θα ενεργοποιηθεί ξανά αυτόματα μόλις λήξει η περίοδος των 48 ωρών." "Εισαγωγή αριθμών" @@ -221,4 +231,6 @@ "Κατάργηση αποκλεισμού αριθμού" "Ανεπιθύμητα" "Ο χρήστης %1$s είναι εκτός σύνδεσης και δεν μπορείτε να έρθετε σε επικοινωνία μαζί του" + + diff --git a/java/com/android/dialer/app/res/values-en-rAU/strings.xml b/java/com/android/dialer/app/res/values-en-rAU/strings.xml index 36d25346dacdb3d5b01d59b5dcaaa24551ce2a85..9229be69014363a4218a2bd167aad6e9aae7a547 100644 --- a/java/com/android/dialer/app/res/values-en-rAU/strings.xml +++ b/java/com/android/dialer/app/res/values-en-rAU/strings.xml @@ -42,6 +42,8 @@ "Call back" "Message" "%1$s: %2$s" + "Dial %s" + "Voicemail number unknown" %1$d Voicemails Voicemail @@ -97,6 +99,12 @@ "Voicemail" "%s sec" "%s min %s sec" + "voicemail" + "voicemails" + "Yes" + "No" + + @string/call_log_header_today "%1$s at %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Calls" "Call blocking" "Voicemail" + + "Call blocking temporarily off" "Call blocking has been disabled because you contacted emergency services from this phone within the last 48 hours. It will be automatically re-enabled once the 48 hour period expires." "Import numbers" @@ -221,4 +231,6 @@ "Unblock number" "Spam" "%1$s is offline and can\'t be reached" + + diff --git a/java/com/android/dialer/app/res/values-en-rGB/strings.xml b/java/com/android/dialer/app/res/values-en-rGB/strings.xml index 36d25346dacdb3d5b01d59b5dcaaa24551ce2a85..9229be69014363a4218a2bd167aad6e9aae7a547 100644 --- a/java/com/android/dialer/app/res/values-en-rGB/strings.xml +++ b/java/com/android/dialer/app/res/values-en-rGB/strings.xml @@ -42,6 +42,8 @@ "Call back" "Message" "%1$s: %2$s" + "Dial %s" + "Voicemail number unknown" %1$d Voicemails Voicemail @@ -97,6 +99,12 @@ "Voicemail" "%s sec" "%s min %s sec" + "voicemail" + "voicemails" + "Yes" + "No" + + @string/call_log_header_today "%1$s at %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Calls" "Call blocking" "Voicemail" + + "Call blocking temporarily off" "Call blocking has been disabled because you contacted emergency services from this phone within the last 48 hours. It will be automatically re-enabled once the 48 hour period expires." "Import numbers" @@ -221,4 +231,6 @@ "Unblock number" "Spam" "%1$s is offline and can\'t be reached" + + diff --git a/java/com/android/dialer/app/res/values-en-rIN/strings.xml b/java/com/android/dialer/app/res/values-en-rIN/strings.xml index 36d25346dacdb3d5b01d59b5dcaaa24551ce2a85..9229be69014363a4218a2bd167aad6e9aae7a547 100644 --- a/java/com/android/dialer/app/res/values-en-rIN/strings.xml +++ b/java/com/android/dialer/app/res/values-en-rIN/strings.xml @@ -42,6 +42,8 @@ "Call back" "Message" "%1$s: %2$s" + "Dial %s" + "Voicemail number unknown" %1$d Voicemails Voicemail @@ -97,6 +99,12 @@ "Voicemail" "%s sec" "%s min %s sec" + "voicemail" + "voicemails" + "Yes" + "No" + + @string/call_log_header_today "%1$s at %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Calls" "Call blocking" "Voicemail" + + "Call blocking temporarily off" "Call blocking has been disabled because you contacted emergency services from this phone within the last 48 hours. It will be automatically re-enabled once the 48 hour period expires." "Import numbers" @@ -221,4 +231,6 @@ "Unblock number" "Spam" "%1$s is offline and can\'t be reached" + + diff --git a/java/com/android/dialer/app/res/values-es-rUS/strings.xml b/java/com/android/dialer/app/res/values-es-rUS/strings.xml index 798742fb174475deac45611e29f2a2476b3375d3..17a1b1438490857090b9582b61e7270cf4692703 100644 --- a/java/com/android/dialer/app/res/values-es-rUS/strings.xml +++ b/java/com/android/dialer/app/res/values-es-rUS/strings.xml @@ -42,6 +42,8 @@ "Llamar" "Mensaje" "%1$s: %2$s" + "Marcar %s" + "Número de correo de voz desconocido" %1$d mensajes de voz mensaje de voz @@ -97,6 +99,12 @@ "Correo de voz" "%s s" "%s min %s s" + "el mensaje de voz" + "los mensajes de voz" + "Sí" + "No" + + @string/call_log_header_today "El %1$s a la hora %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Llamadas" "Bloqueo de llamadas" "Buzón de voz" + + "Bloqueo de llamadas desactivado temporalmente" "Se inhabilitó el bloqueo de llamadas porque te comunicaste con servicios de emergencia en las últimas 48 horas desde este teléfono. Se volverá a habilitar de forma automática una vez que venza el período de 48 horas." "Importar números" @@ -221,4 +231,6 @@ "Desbloquear número" "Spam" "%1$s está sin conexión y no se lo puede contactar" + + diff --git a/java/com/android/dialer/app/res/values-es/strings.xml b/java/com/android/dialer/app/res/values-es/strings.xml index 26ea210c70b3c576af47d3a7ab79fdc48ab13508..15c1299726b6e286a0ba90775fdf3dd86c38db1d 100644 --- a/java/com/android/dialer/app/res/values-es/strings.xml +++ b/java/com/android/dialer/app/res/values-es/strings.xml @@ -42,6 +42,8 @@ "Llamar" "Mensaje" "%1$s: %2$s" + "Marcar %s" + "Número de buzón de voz desconocido" %1$d mensajes de voz mensaje de voz @@ -97,6 +99,11 @@ "Buzón de voz" "%s s" "%s min y %s s" + "mensaje de voz" + "mensajes de voz" + "Sí" + "No" + "¿Eliminar la selección de %1$s?" @string/call_log_header_today "%1$s a las %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Llamadas" "Bloqueo de llamadas" "Buzón de voz" + + "Bloqueo de llamadas desactivado temporalmente" "Se ha inhabilitado el bloqueo de llamadas porque te has puesto en contacto con los servicios de emergencia desde este teléfono en las últimas 48 horas. Se volverá a habilitar automáticamente cuando finalice este periodo de tiempo." "Importar números" @@ -221,4 +230,6 @@ "Desbloquear número" "Spam" "%1$s no tiene conexión y no se puede contactar" + + diff --git a/java/com/android/dialer/app/res/values-et/strings.xml b/java/com/android/dialer/app/res/values-et/strings.xml index de64ecbb2bd2328c6b54a48039b43e7cb8cf1dd1..3dd4ebc04d807f99e0c456f788dc5204f8d2e323 100644 --- a/java/com/android/dialer/app/res/values-et/strings.xml +++ b/java/com/android/dialer/app/res/values-et/strings.xml @@ -42,6 +42,8 @@ "Helista tagasi" "Saada sõnum" "%1$s: %2$s" + "Valige %s" + "Kõneposti number on teadmata" %1$d kõneposti teadet Kõneposti teade @@ -97,6 +99,12 @@ "Kõnepost" "%s s" "%s min %s s" + "kõnepostisõnum" + "kõnepostisõnumid" + "Jah" + "Ei" + + @string/call_log_header_today "%1$s kell %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Kõned" "Kõnede blokeerimine" "Kõnepost" + + "Kõnede blokeerimine on ajutiselt väljas" "Kõnede blokeerimine on keelatud, kuna võtsite sellelt telefonilt viimase 48 tunni jooksul ühendust hädaabiteenustega. See lubatakse 48 tunni möödumisel automaatselt uuesti." "Impordi numbrid" @@ -221,4 +231,6 @@ "Numbri deblokeerimine" "Rämpspost" "%1$s ei ole võrgus ja temaga ei saa ühendust" + + diff --git a/java/com/android/dialer/app/res/values-eu/strings.xml b/java/com/android/dialer/app/res/values-eu/strings.xml index 688de91dc8c9648aacdb11eccae6398c1885f124..e2701f965c19263bcfdcb3e29abf63ee4b0e0435 100644 --- a/java/com/android/dialer/app/res/values-eu/strings.xml +++ b/java/com/android/dialer/app/res/values-eu/strings.xml @@ -42,6 +42,8 @@ "Erantzun deiari" "Mezua" "%1$s: %2$s" + "Markatu %s" + "Erantzungailuaren zenbakia ezezaguna da" Erantzungailuko %1$d mezu Erantzungailuko mezua @@ -97,6 +99,12 @@ "Erantzungailua" "%s s" "%s min %s s" + "ahots-mezua" + "ahots-mezuak" + "Bai" + "Ez" + + @string/call_log_header_today "%1$s (%2$s)" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Deiak" "Deien blokeoa" "Erantzungailua" + + "Deien blokeoa aldi baterako desgaituta" "Deiak blokeatzeko aukera desgaitu egin da, azken 48 orduetan larrialdi-zerbitzuekin harremanetan jarri zarelako telefono honetatik. Berriro gaituko da 48 orduko epea igaro ondoren." "Inportatu zenbakiak" @@ -221,4 +231,6 @@ "Desblokeatu zenbakia" "Spama" "%1$s ez dago konektatuta, eta ezin zara jarri harremanetan berarekin" + + diff --git a/java/com/android/dialer/app/res/values-fa/strings.xml b/java/com/android/dialer/app/res/values-fa/strings.xml index 63461664fe6a3d1e01f1777bca12fd6547ceeaf7..fb1fa8b3157fcb0514aa0d59c24af666f21a9d6f 100644 --- a/java/com/android/dialer/app/res/values-fa/strings.xml +++ b/java/com/android/dialer/app/res/values-fa/strings.xml @@ -42,6 +42,10 @@ "پاسخ تماس" "پیام" "%1$s: %2$s" + + + + %1$d پست صوتی %1$d پست صوتی @@ -97,6 +101,12 @@ "پست صوتی" "%s ثانیه" "%s دقیقه %s ثانیه" + "پست صوتی" + "پست‌های صوتی" + "بله" + "نه" + + @string/call_log_header_today "%1$s ساعت %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "تماس‌ها" "مسدود کردن تماس" "پست صوتی" + + "انسداد تماس موقتاً خاموش است" "چون در ۴۸ ساعت گذشته با این تلفن با سرویس‌های اضطراری تماس گرفتید، انسداد تماس غیرفعال شده است. پس از گذشت ۴۸ ساعت، این قابلیت دوباره فعال می‌شود." "وارد کردن شماره‌ها" @@ -221,4 +233,6 @@ "رفع انسداد شماره" "هرزنامه" "%1$s آفلاین است و در دسترس نمی‌باشد" + + diff --git a/java/com/android/dialer/app/res/values-fi/strings.xml b/java/com/android/dialer/app/res/values-fi/strings.xml index da70c087c4be80cab9893d251195a5806f9ce007..3a03c8e552e6b4cd691515fc1e67c4fc863ad981 100644 --- a/java/com/android/dialer/app/res/values-fi/strings.xml +++ b/java/com/android/dialer/app/res/values-fi/strings.xml @@ -42,6 +42,8 @@ "Soita" "Viesti" "%1$s: %2$s" + "Soita numeroon %s" + "Puhelinvastaajan numero tuntematon" %1$d vastaajaviestiä Vastaajaviesti @@ -97,6 +99,11 @@ "Vastaaja" "%s s" "%s min %s s" + "vastaajaviesti" + "vastaajaviestit" + "Kyllä" + "Ei" + "Poistetaanko %1$s?" @string/call_log_header_today "%1$s klo %2$s" "%1$02d.%2$02d" @@ -192,6 +199,8 @@ "Puhelut" "Puhelujen esto" "Vastaaja" + + "Puheluesto väliaikaisesti pois käytöstä" "Puheluiden estäminen on poistettu käytöstä, koska olet ottanut yhteyttä hätäpalveluihin tästä puhelimesta viimeisen 48 tunnin aikana. Esto otetaan automaattisesti uudelleen käyttöön, kun puhelusta on kulunut 48 tuntia." "Tuo numerot" @@ -221,4 +230,6 @@ "Poista numeron esto" "Roskaposti" "%1$s on offline-tilassa, eikä siihen saada yhteyttä." + + diff --git a/java/com/android/dialer/app/res/values-fr-rCA/strings.xml b/java/com/android/dialer/app/res/values-fr-rCA/strings.xml index 84dcbc89d8d097f7ab19ee058a601534e2e30927..4610e6048b665cd8d86ff973ba9f7416aa51fe2e 100644 --- a/java/com/android/dialer/app/res/values-fr-rCA/strings.xml +++ b/java/com/android/dialer/app/res/values-fr-rCA/strings.xml @@ -42,6 +42,8 @@ "Rappeler" "Message" "%1$s : %2$s" + "Composer le %s" + "Numéro de messagerie vocale inconnu" %1$d message vocal %1$d messages vocaux @@ -97,6 +99,11 @@ "Messagerie vocale" "%s s" "%s min et %s sec" + "message vocal" + "messages vocaux" + "Oui" + "Non" + "Supprimer la sélection (%1$s)?" @string/call_log_header_today "%1$s à %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Appels" "Blocage des appels" "Messagerie vocale" + + "Blocage appels désactivé temporairement" "Le blocage des appels a été désactivé, car vous avez communiqué avec les services d\'urgence à partir de ce téléphone au cours des dernières 48 heures. Le blocage sera réactivé automatiquement après 48 heures." "Importer les numéros" @@ -221,4 +230,6 @@ "Débloquer le numéro" "Pourriel" "%1$s est hors connexion et injoignable" + + diff --git a/java/com/android/dialer/app/res/values-fr/strings.xml b/java/com/android/dialer/app/res/values-fr/strings.xml index 6f03106c43dbd0fedff8b3361d79cdcfa63da282..e1eda7243b1c98e423d2831d2661c9ca1bac5c22 100644 --- a/java/com/android/dialer/app/res/values-fr/strings.xml +++ b/java/com/android/dialer/app/res/values-fr/strings.xml @@ -42,6 +42,8 @@ "Rappeler" "Envoyer un SMS" "%1$s : %2$s" + "Composer le %s" + "Numéro de messagerie vocale inconnu" %1$d message vocal %1$d messages vocaux @@ -97,6 +99,11 @@ "Messagerie vocale" "%s secondes" "%s min et %s s" + "message vocal" + "messages vocaux" + "Oui" + "Non" + "Supprimer les messages vocaux sélectionnés (%1$s) ?" @string/call_log_header_today "%1$s à %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Appels" "Blocage des appels" "Messagerie vocale" + + "Blocage appels désactivé temporairement" "Le blocage des appels a été désactivé, car vous avez contacté les services d\'urgence à l\'aide de ce téléphone au cours des dernières 48 heures. Le blocage sera réactivé automatiquement après 48 heures." "Importer les numéros" @@ -221,4 +230,6 @@ "Débloquer le numéro" "Spam" "%1$s est injoignable, car non connecté" + + diff --git a/java/com/android/dialer/app/res/values-gl/strings.xml b/java/com/android/dialer/app/res/values-gl/strings.xml index 4d4e69377a9c22a71276609a4f251378771e60c5..2a79835c2e7058dc5463c902b3f84634b2460599 100644 --- a/java/com/android/dialer/app/res/values-gl/strings.xml +++ b/java/com/android/dialer/app/res/values-gl/strings.xml @@ -42,6 +42,8 @@ "Devolver chamada" "Mensaxe" "%1$s: %2$s" + "Marca o %s" + "Número de correo de voz descoñecido" %1$d correos de voz Correo de voz @@ -97,6 +99,12 @@ "Correo de voz" "%s s" "%s min %s s" + "correo de voz" + "correos de voz" + "Si" + "Non" + + @string/call_log_header_today "%1$s ás %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Chamadas" "Bloqueo de chamadas" "Correo de voz" + + "O bloqueo de chamadas desactivouse temporalmente" "O bloqueo de chamadas desactivouse porque contactaches cos servizos de emerxencias desde este teléfono nas últimas 48 horas. Volverase activar automaticamente unha vez que pase o período de 48 horas." "Importar números" @@ -221,4 +231,6 @@ "Desbloquear número" "Spam" "Non se pode contactar con %1$s porque está sen conexión" + + diff --git a/java/com/android/dialer/app/res/values-gu/strings.xml b/java/com/android/dialer/app/res/values-gu/strings.xml index 726d473a1278e6a5cde6649297f1633f53f50ee0..940dea02812fdbd1589b814d338af20aa27a0e92 100644 --- a/java/com/android/dialer/app/res/values-gu/strings.xml +++ b/java/com/android/dialer/app/res/values-gu/strings.xml @@ -42,6 +42,8 @@ "કૉલ બેક" "સંદેશ" "%1$s: %2$s" + "%s ડાયલ કરો" + "વૉઇસમેઇલ નંબર અજાણ" %1$d વૉઇસમેઇલ્સ %1$d વૉઇસમેઇલ્સ @@ -97,6 +99,12 @@ "વૉઇસમેઇલ" "%s સેકંડ" "%s મિ %s સે" + "વૉઇસમેઇલ" + "વૉઇસમેઇલ" + "હા" + "નહીં" + + @string/call_log_header_today "%1$s નાં રોજ %2$s વાગ્યે" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "કૉલ્સ" "કૉલ અવરોધ" "વૉઇસમેઇલ" + + "કૉલ અવરોધિત કરવાનું અસ્થાયીરૂપે બંધ છે" "કૉલ અવરોધિત કરવાનું અક્ષમ કરવામાં આવ્યું છે કારણ કે તમે આ ફોનમાંથી છેલ્લા 48 કલાકમાં કટોકટીની સેવાઓનો સંપર્ક કર્યો હતો. એકવાર 48 કલાકનો સમયગાળો સમાપ્ત થાય, પછી તે આપમેળે ફરીથી સક્ષમ કરવામાં આવશે." "નંબર્સ આયાત કરો" @@ -221,4 +231,6 @@ "નંબર અનાવરોધિત કરો" "સ્પામ" "%1$s ઑફલાઇન છે અને તેના સુધી પહોંચી શકતાં નથી" + + diff --git a/java/com/android/dialer/app/res/values-hi/strings.xml b/java/com/android/dialer/app/res/values-hi/strings.xml index f44d45bcbabe11aa6cb95c82cd129c8c76f4e8d3..c4f135b1682f5c9ddc1d6dad5038af78f4a41c3a 100644 --- a/java/com/android/dialer/app/res/values-hi/strings.xml +++ b/java/com/android/dialer/app/res/values-hi/strings.xml @@ -42,6 +42,8 @@ "वापस कॉल करें" "संदेश" "%1$s: %2$s" + "%s डायल करें" + "वॉइसमेल नंबर अज्ञात" %1$d वॉइसमेल %1$d वॉइसमेल @@ -97,6 +99,12 @@ "वॉयस मेल" "%s सेकंड" "%s मि. %s से." + "वॉयसमेल" + "वॉयसमेल" + "हां" + "नहीं" + + @string/call_log_header_today "%1$s को %2$s बजे" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "कॉल" "कॉल अवरुद्ध करें" "वॉइसमेल" + + "कॉल अवरुद्ध करना अस्‍थायी रूप से बंद है" "कॉल अवरुद्ध किए जाने को अक्षम कर दिया गया है क्योंकि पिछले 48 घंटों में आपने इस फ़ोन से आपातकालीन सेवाओं से संपर्क किया है. 48 घंटे की अवधि बीत जाने पर यह अपने आप फिर से सक्षम हो जाएगी." "नंबर आयात करें" @@ -221,4 +231,6 @@ "नंबर अनवरोधित करें" "स्पैम" "%1$s ऑफ़लाइन हैं और उन तक नहीं पहुंचा जा सकता" + + diff --git a/java/com/android/dialer/app/res/values-hr/strings.xml b/java/com/android/dialer/app/res/values-hr/strings.xml index 0e5d0d0ec5d5679224feb8876bcb61fa545c86b0..fb96256f5231f35528987df308824ac5db2758be 100644 --- a/java/com/android/dialer/app/res/values-hr/strings.xml +++ b/java/com/android/dialer/app/res/values-hr/strings.xml @@ -42,6 +42,10 @@ "Povratni poziv" "Poruka" "%1$s: %2$s" + + + + %1$d poruka govorne pošte %1$d poruke govorne pošte @@ -98,6 +102,12 @@ "Govorna pošta" "%s s" "%s min %s s" + "poruka govorne pošte" + "poruke govorne pošte" + "Da" + "Ne" + + @string/call_log_header_today "%1$s u %2$s" "%1$02d.%2$02d" @@ -194,6 +204,8 @@ "Pozivi" "Blokiranje poziva" "Govorna pošta" + + "Blokiranje poziva privremeno isključeno" "Blokiranje poziva onemogućeno je jer ste kontaktirali hitne službe s ovog telefona u posljednjih 48 sati. Automatski će se ponovo omogućiti kada prođe 48 sati." "Uvoz brojeva" @@ -223,4 +235,6 @@ "Deblokiranje broja" "Neželjena pošta" "%1$s nije online i nije dostupan" + + diff --git a/java/com/android/dialer/app/res/values-hu/strings.xml b/java/com/android/dialer/app/res/values-hu/strings.xml index fcc4454e26a6a73546bc3df217d756cec357070d..a39c5846f94b9841bb08d51ccde980f7fe903fe7 100644 --- a/java/com/android/dialer/app/res/values-hu/strings.xml +++ b/java/com/android/dialer/app/res/values-hu/strings.xml @@ -42,6 +42,10 @@ "Visszahívás" "Üzenet" "%1$s: %2$s" + + + + %1$d hangpostaüzenet Hangpostaüzenet @@ -97,6 +101,12 @@ "Hangposta" "%s másodperc" "%s perc %s másodperc" + "hangpostaüzenetet" + "hangpostaüzeneteket" + "Igen" + "Nem" + + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Hívások" "Hívásletiltás" "Hangposta" + + "Hívástiltás átmenetileg felfüggesztve" "Felfüggesztettük a hívások tiltását, mert az elmúlt 48 órában tárcsázta a segélyhívót erről a telefonról. A funkciót automatikusan újból engedélyezzük 48 óra elteltével." "Számok importálása" @@ -221,4 +233,6 @@ "Szám tiltásának feloldása" "Spam" "%1$s offline, és nem érhető el." + + diff --git a/java/com/android/dialer/app/res/values-hy/strings.xml b/java/com/android/dialer/app/res/values-hy/strings.xml index 008d34f176dbe11a9c3dfeadf05fe5bcbef69eb2..362c570484de8952959121b0f0ff4af9fca2b68a 100644 --- a/java/com/android/dialer/app/res/values-hy/strings.xml +++ b/java/com/android/dialer/app/res/values-hy/strings.xml @@ -42,6 +42,8 @@ "Հետ զանգել" "Հաղորդագրություն" "%1$s՝ %2$s" + "Զանգել %s համարին" + "Ձայնային փոստի համարն անհայտ է" %1$d ձայնային փոստ %1$d ձայնային փոստ @@ -97,6 +99,11 @@ "Ձայնային փոստ" "%s վրկ" "%s րոպե %s վայրկյան" + "ձայնային հաղորդագրություն" + "ձայնային հաղորդագրություններ" + "Այո" + "Ոչ" + "Ջնջե՞լ նշված %1$sը" @string/call_log_header_today "%1$s-ին, ժամը %2$s-ին" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Զանգեր" "Զանգերի արգելափակում" "Ձայնային փոստ" + + "Զանգերի արգելափակումը կասեցվել է" "Զանգերի արգելափակումը կասեցվել է, քանի որ վերջին 48 ժամվա ընթացքում դուք այս հեռախոսից զանգել եք արտակարգ իրավիճակների ծառայություններին: 48 ժամ տևողությամբ ժամանակահատվածի ավարտից հետո այն ավտոմատ կերպով կվերամիացվի:" "Ներմուծել համարները" @@ -221,4 +230,6 @@ "Արգելաբացել համարը" "Լցոն" "%1$s օգտատերը միացած չէ ցանցին և անհասանելի է" + + diff --git a/java/com/android/dialer/app/res/values-in/strings.xml b/java/com/android/dialer/app/res/values-in/strings.xml index a133a65424844481426443129096d1e4f16a9abb..ca7341ae33d06464125884a047e19073df6486d7 100644 --- a/java/com/android/dialer/app/res/values-in/strings.xml +++ b/java/com/android/dialer/app/res/values-in/strings.xml @@ -42,6 +42,10 @@ "Telepon" "Pesan" "%1$s: %2$s" + + + + %1$d Pesan suara Pesan suara @@ -97,6 +101,12 @@ "Kotak Pesan" "%s dtk" "%s mnt %s dtk" + "pesan suara" + "pesan suara" + "Ya" + "Tidak" + + @string/call_log_header_today "%1$s pukul %2$s" "%1$02d.%2$02d" @@ -131,7 +141,7 @@ "Batalkan" "Telepon %s" "Buat kontak baru" - "Tambah ke kontak" + "Tambahkan ke kontak" "Kirim SMS" "Lakukan video call" "Blokir nomor" @@ -192,6 +202,8 @@ "Panggilan telepon" "Pemblokiran panggilan telepon" "Pesan Suara" + + "Blokir panggilan dinonaktifkan sementara" "Pemblokiran panggilan telepon telah dinonaktifkan karena Anda menghubungi layanan darurat dari telepon ini dalam 48 jam terakhir. Akan diaktifkan kembali secara otomatis setelah masa 48 jam berakhir." "Impor nomor" @@ -221,4 +233,6 @@ "Bebaskan nomor" "Spam" "%1$s sedang offline dan tidak dapat dijangkau" + + diff --git a/java/com/android/dialer/app/res/values-is/strings.xml b/java/com/android/dialer/app/res/values-is/strings.xml index c9dc4f37153f2f39fd39610b6307873481a2c460..a8a9ae15d8627715c4f6145b77f52956879acfa3 100644 --- a/java/com/android/dialer/app/res/values-is/strings.xml +++ b/java/com/android/dialer/app/res/values-is/strings.xml @@ -42,6 +42,8 @@ "Hringja til baka" "Skilaboð" "%1$s: %2$s" + "Hringja í %s" + "Talhólfsnúmer ekki þekkt" %1$d talhólfsskilaboð %1$d talhólfsskilaboð @@ -97,6 +99,12 @@ "Talhólf" "%s sek." "%s mín. og %s sek." + "talhólfsskilaboð" + "talhólfsskilaboð" + "Já" + "Nei" + + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Símtöl" "Lokað fyrir símtöl" "Talhólf" + + "Tímabundið slökkt á lokun fyrir símtöl" "Lokun fyrir símtöl hefur verið gerð óvirk vegna þess að þú hafðir samband við neyðarþjónustu úr þessum síma á undanförnum tveimur sólarhringum. Lokunin verður aftur virk að þessum tveimur sólarhringum liðnum." "Flytja inn númer" @@ -221,4 +231,6 @@ "Taka númer af bannlista" "Ruslnúmer" "%1$s er án nettengingar og ekki er hægt að ná í viðkomandi" + + diff --git a/java/com/android/dialer/app/res/values-it/strings.xml b/java/com/android/dialer/app/res/values-it/strings.xml index 1465c91e1ec8090213025a8a979c23eadbdf5ce1..7fc581115ce656b14e16c00af94d7558af16b390 100644 --- a/java/com/android/dialer/app/res/values-it/strings.xml +++ b/java/com/android/dialer/app/res/values-it/strings.xml @@ -42,6 +42,8 @@ "Richiama" "Messaggio" "%1$s: %2$s" + "Componi %s" + "Numero segreteria sconosciuto" %1$d messaggi in segreteria Messaggio in segreteria @@ -97,6 +99,12 @@ "Segreteria" "%s secondi" "%s min %s s" + "messaggio vocale" + "messaggi vocali" + "Sì" + "No" + + @string/call_log_header_today "%1$s alle ore %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Chiamate" "Blocco delle chiamate" "Messaggi vocali" + + "Blocco chiamate temporaneam. disattivato" "Il blocco chiamate è stato disattivato perché hai contattato servizi di emergenza da questo telefono nelle ultime 48 ore. Verrà riattivato automaticamente una volta trascorso il periodo di 48 ore." "Importa numeri" @@ -221,4 +231,6 @@ "Sblocca numero" "Spam" "%1$s è offline e non può essere raggiunto" + + diff --git a/java/com/android/dialer/app/res/values-iw/strings.xml b/java/com/android/dialer/app/res/values-iw/strings.xml index efb65532242459ff4da1283d32c58ad823a6e6e4..743d45505a114894af3e8e8d94ef83793c1d1b24 100644 --- a/java/com/android/dialer/app/res/values-iw/strings.xml +++ b/java/com/android/dialer/app/res/values-iw/strings.xml @@ -42,6 +42,8 @@ "התקשר חזרה" "הודעה" "%1$s: %2$s" + "‏חיוג אל ‎%s‎" + "המספר של תא הדואר הקולי אינו ידוע" %1$d הודעות דואר קולי %1$d הודעות דואר קולי @@ -99,6 +101,11 @@ "דואר קולי" "%s שניות" "%s דק\' %s שנ\'" + "ההודעה הקולית" + "ההודעות הקוליות" + "כן" + "לא" + "האם למחוק את %1$s שבחרת?" @string/call_log_header_today "%1$s ב-%2$s" "%1$02d:%2$02d" @@ -196,6 +203,8 @@ "שיחות" "חסימת שיחות" "דואר קולי" + + "חסימת השיחות מושבתת באופן זמני" "חסימת השיחות הושבתה מפני שיצרת קשר מטלפון זה עם שירותי חירום במהלך 48 השעות האחרונות. הפונקציה תופעל מחדש באופן אוטומטי בתום 48 השעות." "יבא מספרים" @@ -225,4 +234,6 @@ "בטל חסימת מספר" "ספאם" "לא ניתן להתקשר כי המכשיר של %1$s לא מחובר כרגע" + + diff --git a/java/com/android/dialer/app/res/values-ja/strings.xml b/java/com/android/dialer/app/res/values-ja/strings.xml index ccdf0175900e7b16067414c2f1484197a1a0be29..72bc2debb706a38130c0b3c507ab5da0383d4dd7 100644 --- a/java/com/android/dialer/app/res/values-ja/strings.xml +++ b/java/com/android/dialer/app/res/values-ja/strings.xml @@ -42,6 +42,8 @@ "コールバック" "メッセージ" "%1$s さん: %2$s" + "%s 宛に発信" + "ボイスメールの番号が不明です" %1$d件のボイスメール 1件のボイスメール @@ -97,6 +99,11 @@ "ボイスメール" "%s秒" "%s%s秒" + "ボイスメール" + "ボイスメール" + "はい" + "いいえ" + "選択した%1$sを削除しますか?" @string/call_log_header_today "%1$s%2$s" "%1$02d%2$02d 秒" @@ -192,6 +199,8 @@ "通話" "着信のブロック" "ボイスメール" + + "着信のブロックは一時的にOFFです" "このスマートフォンから緊急通報番号への発信が過去48時間以内に行われているため、着信のブロックは無効になっています。48時間経過すると、着信のブロックは自動的に有効になります。" "番号をインポート" @@ -221,4 +230,6 @@ "番号のブロックを解除" "スパム" "%1$s さんはオフラインのため、通話を受信できません" + + diff --git a/java/com/android/dialer/app/res/values-ka/strings.xml b/java/com/android/dialer/app/res/values-ka/strings.xml index bebf1c5420ed9b5d88af794bf31a12a2b22a1379..befdd3aca5afff8ed319462a0813e21b3e05d462 100644 --- a/java/com/android/dialer/app/res/values-ka/strings.xml +++ b/java/com/android/dialer/app/res/values-ka/strings.xml @@ -42,6 +42,10 @@ "გადარეკვა" "შეტყობინება" "%1$s: %2$s" + + + + %1$d ხმოვანი ფოსტა ხმოვანი ფოსტა @@ -97,6 +101,12 @@ "ხმოვანი ფოსტა" "%s წმ" "%s მინ %s წამ" + "ხმოვანი ფოსტა" + "ხმოვანი ფოსტა" + "დიახ" + "არა" + + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "ზარები" "ზარების დაბლოკვა" "ხმოვანი ფოსტა" + + "ზარების დაბლოკვა დროებით გამოირთო" "ზარების დაბლოკვა გაითიშა, რადგან ბოლო 48 საათში ამ ტელეფონიდან საგანგებო სამსახურებს დაუკავშირდით. 48 საათის გასვლის შემდეგ ის ავტომატურად ჩაირთვება." "ნომრების იმპორტი" @@ -221,4 +233,6 @@ "ნომრის განბლოკვა" "სპამი" "%1$s ხაზგარეშეა და ვერ დაუკავშირდებით" + + diff --git a/java/com/android/dialer/app/res/values-kk/strings.xml b/java/com/android/dialer/app/res/values-kk/strings.xml index 7fa5d33eceb84b5af96e7daf2382d0d4f589546e..8ed6661093e6b9befb1497aab28ce9795b3d9a99 100644 --- a/java/com/android/dialer/app/res/values-kk/strings.xml +++ b/java/com/android/dialer/app/res/values-kk/strings.xml @@ -42,6 +42,8 @@ "Қоңырау шалу" "Хабар" "%1$s: %2$s" + "%s нөмірін теру" + "Дауыстық пошта нөмірі белгісіз" %1$d дауыстық хабар Дауыстық хабар @@ -97,6 +99,12 @@ "Дауыстық пошта" "%s сек." "%s мин %s сек" + "дауыстық хабар" + "дауыстық хабарлар" + "Иә" + "Жоқ" + + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Қоңыраулар" "Қоңырауларға тыйым салу" "Дауыстық хабар" + + "Қоңырауларға тыйым салу уақытша өшірулі" "Қоңырауларға тыйым салу өшірілді, өйткені сіз соңғы 48 сағат ішінде осы телефоннан төтенше қызметтерге хабарластыңыз. Ол 48 сағаттық кезең өткеннен кейін автоматты түрде қайта қосылады." "Нөмірлерді импорттау" @@ -221,4 +231,6 @@ "Нөмірді бөгеуден шығару" "Спам" "%1$s желіден тыс және байланысу мүмкін емес" + + diff --git a/java/com/android/dialer/app/res/values-km/strings.xml b/java/com/android/dialer/app/res/values-km/strings.xml index 3b6fe9e710703c6c950a5bedf6cb513fa2049ceb..298070806d4fe391732e7a177b87760a01114e6f 100644 --- a/java/com/android/dialer/app/res/values-km/strings.xml +++ b/java/com/android/dialer/app/res/values-km/strings.xml @@ -42,6 +42,8 @@ "ហៅ​ទៅ​វិញ" "សារ" "%1$s: %2$s" + "ហៅ​ទូរសព្ទ​ទៅកាន់ %s" + "មិន​ស្គាល់​លេខ​សារ​ជា​សំឡេង​ទេ" សារជាសម្លេង %1$d សារជាសម្លេង @@ -97,6 +99,11 @@ "សារ​ជា​សំឡេង" "%s វិនាទី" "%s នាទី %s វិនាទី" + "សារ​ជា​សំឡេង" + "សារ​ជា​សំឡេង" + "បាទ/ចាស" + "ទេ" + "លុប %1$s ដែល​បាន​ជ្រើសរើស?" @string/call_log_header_today "%1$s នៅម៉ោង %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "ការហៅ" "ការរារាំងការហៅ" "សារ​ជា​សំឡេង" + + "ការរារាំងការហៅត្រូវបានបិទជាបណ្តោះអាសន្ន" "ការរារាំងការហៅត្រូវបានបិទដំណើរការ ដោយសារតែអ្នកបានទាក់ទងទៅសេវាអាសន្នចេញពីទូរស័ព្ទនេះក្នុងចន្លោះពេល 48 ម៉ោងកន្លងមកនេះ។ វានឹងបើកដំណើរការឡើងវិញ បន្ទាប់ពីរយៈពេល 48 ម៉ោងផុតកំណត់។" "នាំចូលលេខ" @@ -221,4 +230,6 @@ "ឈប់ទប់ស្កាត់លេខ" "សារ​ឥតបានការ" "%1$s មិន​នៅ​លើ​អ៊ីនធឺណិត និង​មិន​អាច​ទាក់ទង​បាន​ទេ" + + diff --git a/java/com/android/dialer/app/res/values-kn/strings.xml b/java/com/android/dialer/app/res/values-kn/strings.xml index 68280f1f3f6ef078972e72bc205883cb702aa179..ff780f99c0c67256154c9587f7d7d4734701998a 100644 --- a/java/com/android/dialer/app/res/values-kn/strings.xml +++ b/java/com/android/dialer/app/res/values-kn/strings.xml @@ -42,6 +42,8 @@ "ಮರಳಿ ಕರೆ ಮಾಡಿ" "ಸಂದೇಶ" "%1$s: %2$s" + "%s ಗೆ ಡಯಲ್‌‌ ಮಾಡಿ" + "ಅಪರಿಚಿತ ಧ್ವನಿಮೇಲ್‌ ಸಂಖ್ಯೆ" %1$d ಧ್ವನಿಮೇಲ್‌ಗಳು %1$d ಧ್ವನಿಮೇಲ್‌ಗಳು @@ -97,6 +99,12 @@ "ಧ್ವನಿಮೇಲ್" "%s ಸೆಕೆಂ" "%s ನಿಮಿ %s ಸೆಕೆಂ" + "ಧ್ವನಿಮೇಲ್" + "ಧ್ವನಿಮೇಲ್‌ಗಳು" + "ಹೌದು" + "ಇಲ್ಲ" + + @string/call_log_header_today "%1$s ರಂದು %2$s ಗಂಟೆಗೆ" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "ಕರೆಗಳು" "ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆ" "ಧ್ವನಿಮೇಲ್" + + "ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆ ತಾತ್ಕಾಲಿಕ ಆಫ್ ಮಾಡಲಾಗಿದೆ" "ನೀವು ಕಳೆದ 48 ಗಂಟೆಗಳಲ್ಲಿ ಈ ಫೋನ್‌ನಿಂದ ತುರ್ತು ಸೇವೆಗಳಿಗೆ ಸಂಪರ್ಕಿಸಿರುವ ಕಾರಣದಿಂದ ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಒಮ್ಮೆ 48 ಗಂಟೆಗಳ ಅವಧಿಯು ಮುಕ್ತಾಯಗೊಂಡ ನಂತರ ಅದನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಸಕ್ರಿಯಗೊಳಿಸಲಾಗುವುದು." "ಸಂಖ್ಯೆಗಳನ್ನು ಆಮದು ಮಾಡಿ" @@ -221,4 +231,6 @@ "ಸಂಖ್ಯೆಯನ್ನು ಅನಿರ್ಬಂಧಿಸು" "ಸ್ಪ್ಯಾಮ್" "%1$s ಆಫ್‌ಲೈನ್ ಆಗಿದ್ದಾರೆ ಮತ್ತು ಅವರನ್ನು ತಲುಪಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ" + + diff --git a/java/com/android/dialer/app/res/values-ko/strings.xml b/java/com/android/dialer/app/res/values-ko/strings.xml index f72a691390ae828e1920fead31c769c8dab6f318..cdd0d520592ae84b3e5f841679ea64b74405cfeb 100644 --- a/java/com/android/dialer/app/res/values-ko/strings.xml +++ b/java/com/android/dialer/app/res/values-ko/strings.xml @@ -42,6 +42,8 @@ "통화하기" "메시지" "%1$s: %2$s" + "%s(으)로 전화걸기" + "알 수 없는 음성사서함 번호" 음성메일 %1$d 음성메일 @@ -97,6 +99,12 @@ "음성사서함" "%s초" "%s%s초" + "음성사서함" + "음성사서함" + "예" + "아니요" + + @string/call_log_header_today "%1$s %2$s" "%1$02d%2$02d초" @@ -192,6 +200,8 @@ "통화" "통화 차단" "음성사서함" + + "통화 차단 기능이 일시적으로 중지됨" "지난 48시간 이내에 이 휴대전화를 사용해 응급 서비스에 연락했으므로 통화 차단 기능이 중지되었습니다. 48시간이 지나면 통화 차단 기능이 자동으로 다시 사용 설정됩니다." "번호 가져오기" @@ -221,4 +231,6 @@ "번호 차단 해제" "스팸" "%1$s님은 오프라인 상태이며 연락할 수 없습니다." + + diff --git a/java/com/android/dialer/app/res/values-ky/strings.xml b/java/com/android/dialer/app/res/values-ky/strings.xml index 34d87da090728067dbed39f1b8594b5f73443f6c..0784a3e07d5af11b546ed595ce425cfe91fa551d 100644 --- a/java/com/android/dialer/app/res/values-ky/strings.xml +++ b/java/com/android/dialer/app/res/values-ky/strings.xml @@ -42,6 +42,10 @@ "Кайра чалуу" "Билдирүү" "%1$s: %2$s" + + + + %1$d Үн каты Үн каты @@ -97,6 +101,12 @@ "Үн почтасы" "%s сек." "%s мүн. %s сек." + "үн почтасы" + "үн почталары" + "Ооба" + "Жок" + + @string/call_log_header_today "%1$s саат %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Чалуулар" "Чалууларды бөгөттөө" "Үн почтасы" + + "Чалууну бөгөттөө убактылуу өчүрүлгөн" "Акыркы 48 саат ичинде бул телефондон өзгөчө кырдаал кызматына байланышкандыктан чалууну бөгөттөө өчүрүлдү. 48 сааттык мөөнөтү аяктагандан кийин ал автоматтык түрдө кайра иштетилет." "Номерлерди импорттоо" @@ -221,4 +233,6 @@ "Номерди бөгөттөн чыгаруу" "Спам" "%1$s оффлайн режиминде болгондуктан, байланышууга болбойт" + + diff --git a/java/com/android/dialer/app/res/values-lo/strings.xml b/java/com/android/dialer/app/res/values-lo/strings.xml index 4bdb11338988c5112f2394d62f3ad5a84c022d40..d7b8f320718d6d0f06d1f868793825cf10d896b1 100644 --- a/java/com/android/dialer/app/res/values-lo/strings.xml +++ b/java/com/android/dialer/app/res/values-lo/strings.xml @@ -42,6 +42,8 @@ "ໂທກັບ" "ຂໍ້ຄວາມ" "%1$s: %2$s" + "ໂທຫາ %s" + "ບໍ່ຮູ້ຈັກເບີຂໍ້ຄວາມສຽງ" %1$d ຂໍ້ຄວາມສຽງ ຂໍ້ຄວາມສຽງ @@ -97,6 +99,12 @@ "ຂໍ້ຄວາມສຽງ" "%s ວິນາທີ" "%s ນ​ທ %s ວິ" + "ຂໍ້ຄວາມສຽງ" + "ຂໍ້ຄວາມສຽງ" + "ແມ່ນແລ້ວ" + "ບໍ່" + + @string/call_log_header_today "%1$s ເວລາ %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "​ການ​ໂທ" "ການບ​ລັອກ​ສາຍ​ໂທ" "ຂໍ້ຄວາມສຽງ" + + "ການບ​ລັອກ​ສາຍ​ໂທ​ປິດ​ຊົ່ວ​ຄາວ" "ການບ​ລັອກ​ສາຍ​ໂທ​ຖືກ​ປິດ​ໃຊ້​ງານ​ແລ້ວ ເພາະ​ວ່າ​ທ່ານ​ໄດ້​ຕິດ​ຕໍ່​ຫາ​ຝ່າຍ​ບໍ​ລິ​ການ​ສຸກ​ເສີນ​ຈາກ​ໂທ​ລະ​ສັບ​ນີ້​ພາຍ​ໃນ 48 ຊົ່ວ​ໂມງ​ສຸດ​ທ້າຍ. ມັນ​ຈະ​ຖືກ​ເປີດ​ໃຊ້​ງານ​ອີກ​ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດ ເມື່ອ​ໝົດ​ໄລ​ຍະ 48 ຊົ່ວ​ໂມງ​ໄປ​ແລ້ວ." "ນຳ​ຕົວ​ເລກ​ເຂົ້າ" @@ -221,4 +231,6 @@ "ປົດ​ບ​ລັອກ​ໝາຍ​ເລກ" "ສະແປມ" "%1$s ອອບລາຍຢູ່ ແລະ ບໍ່ສາມາດຕິດຕໍ່ຫາໄດ້" + + diff --git a/java/com/android/dialer/app/res/values-lt/strings.xml b/java/com/android/dialer/app/res/values-lt/strings.xml index 5266dd1b8ab6eab7bc17e4888e99b3e13d260384..eaa11cbc775a04235043eba0ee861731479b5117 100644 --- a/java/com/android/dialer/app/res/values-lt/strings.xml +++ b/java/com/android/dialer/app/res/values-lt/strings.xml @@ -42,6 +42,8 @@ "Perskambinti" "Siųsti pranešimą" "%1$s: „%2$s“" + "Rinkti %s" + "Nežinomas balso pašto numeris" %1$d balso pašto pranešimas %1$d balso pašto pranešimai @@ -99,6 +101,12 @@ "Balso paštas" "%s sek." "%s min. %s sek." + "balso pašto praneš." + "balso pašto praneš." + "Taip" + "Ne" + + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Skambučiai" "Skambučių blokavimas" "Balso paštas" + + "Skamb. blokavimo funkcija laikinai išj." "Skambučių blokavimo funkcija buvo išjungta, nes iš šio telefono buvote susisiekę su pagalbos tarnybomis per pastarąsias 48 val. Ši funkcija bus automatiškai įgalinta iš naujo, kai 48 val. laikotarpis pasibaigs." "Importuoti numerius" @@ -225,4 +235,6 @@ "Panaikinti numerio blokavimą" "Šlamštas" "%1$s yra neprisijungęs (-usi) ir su juo (ja) negalima susisiekti" + + diff --git a/java/com/android/dialer/app/res/values-lv/strings.xml b/java/com/android/dialer/app/res/values-lv/strings.xml index e36a47eae861a7215ecd6fb1d220769025e0c4c3..3c73cd58099601c7293dd7d7337d8204ce2a6fb2 100644 --- a/java/com/android/dialer/app/res/values-lv/strings.xml +++ b/java/com/android/dialer/app/res/values-lv/strings.xml @@ -42,6 +42,8 @@ "Atzvanīt" "Sūtīt ziņojumu" "%1$s: %2$s" + "Sastādiet šādu numuru: %s" + "Balss pasta numurs nav zināms." %1$d balss pasta ziņojumi %1$d balss pasta ziņojums @@ -98,6 +100,12 @@ "Balss pasts" "%s s" "%s min %s s" + "balss pasta ziņojums" + "balss pasta ziņojumi" + "Jā" + "Nē" + + @string/call_log_header_today "%1$s plkst. %2$s" "%1$02d:%2$02d" @@ -194,6 +202,8 @@ "Zvani" "Zvanu bloķēšana" "Balss pasts" + + "Zvanu bloķēšana ir īslaicīgi izslēgta" "Zvanu bloķēšana ir atspējota, jo pēdējo 48 stundu laikā jūs sazinājāties ar ārkārtas palīdzības dienestiem, izmantojot šo tālruni. Zvanu bloķēšana tiks automātiski iespējota, tiklīdz beigsies 48 stundu periods." "Importēt numurus" @@ -223,4 +233,6 @@ "Atbloķēt numuru" "Nevēlami zvani" "Lietotājs %1$s ir bezsaistē un nav sasniedzams" + + diff --git a/java/com/android/dialer/app/res/values-mk/strings.xml b/java/com/android/dialer/app/res/values-mk/strings.xml index 742250d0367f15f2acaeb8bc53463152f6b673dc..016821d96665f60e47ae51a7fff75ef213594f1b 100644 --- a/java/com/android/dialer/app/res/values-mk/strings.xml +++ b/java/com/android/dialer/app/res/values-mk/strings.xml @@ -42,6 +42,8 @@ "Повикува назад" "Порака" "%1$s: %2$s" + "Бирајте %s" + "Бројот на говорната пошта е непознат" %1$d говорна порака %1$d говорни пораки @@ -97,6 +99,12 @@ "Говорна пошта" "%s сек." "%s мин. %s сек." + "говорна пошта" + "говорни пораки" + "Да" + "Не" + + @string/call_log_header_today "%1$s во %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Повици" "Блокирање повик" "Говорна пошта" + + "Блокирањето повик е привремено исклучено" "Блокирањето повици е исклучено бидејќи ја контактиравте службата за итни случаи од телефонов во изминатите 48 часа. Повторно ќе се овозможи автоматски откако ќе истече периодот од 48 часа." "Увези броеви" @@ -221,4 +231,6 @@ "Одблокирај го бројот" "Спам" "Контактот %1$s е офлајн и недостапен" + + diff --git a/java/com/android/dialer/app/res/values-ml/strings.xml b/java/com/android/dialer/app/res/values-ml/strings.xml index 857973aaae3591f3866752992820a511d264d46f..081a05a04c9e89bbdc0d045ffa95986fa0523d94 100644 --- a/java/com/android/dialer/app/res/values-ml/strings.xml +++ b/java/com/android/dialer/app/res/values-ml/strings.xml @@ -42,6 +42,8 @@ "കോൾബാക്ക്" "സന്ദേശം" "%1$s: %2$s" + "%s ഡയൽ ചെയ്യുക" + "വോയ്‌സ്‌മെയിൽ നമ്പർ അജ്ഞാതമാണ്" %1$d വോയ്‌സ്‌മെയിലുകൾ വോയ്‌സ്‌മെയിൽ @@ -97,6 +99,12 @@ "വോയ്‌സ്‌മെയിൽ" "%s സെക്കൻഡ്" "%s മി. %s സെ." + "വോയ്‌സ്‌മെയിൽ" + "വോയ്‌സ്മെയിലുകൾ" + "അതെ" + "ഇല്ല" + + @string/call_log_header_today "%1$s, %2$s-ന്" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "കോളുകൾ" "കോൾ ബ്ലോക്കുചെയ്യൽ" "വോയ്സ് മെയില്‍" + + "കോൾ ബ്ലോക്കുചെയ്യൽ താൽക്കാലികമായി ഓഫാണ്" "കഴിഞ്ഞ 48 മണിക്കൂറിനുള്ളിൽ നിങ്ങൾ ഈ ഫോണിൽ നിന്ന് അടിയന്തിര സേവനങ്ങളുമായി ബന്ധപ്പെട്ടതിനാൽ കോൾ ബ്ലോക്കുചെയ്യൽ പ്രവർത്തനരഹിതമാക്കി. 48 മണിക്കൂർ സമയപരിധി കഴിഞ്ഞയുടൻ ഇത് സ്വയമേവ പ്രവർത്തനക്ഷമമാക്കപ്പെടും." "നമ്പറുകൾ ഇമ്പോർട്ടുചെയ്യുക" @@ -221,4 +231,6 @@ "നമ്പർ അൺബ്ലോക്കുചെയ്യുക" "സ്‌പാം" "%1$s ഓഫ്‌ലൈനായതിനാൽ കോൾ ചെയ്യാനാവില്ല" + + diff --git a/java/com/android/dialer/app/res/values-mn/strings.xml b/java/com/android/dialer/app/res/values-mn/strings.xml index decd081168ab59aacf58ef0e804cee241b892ad1..16f7e1ad171043fce8ceb74a09d2e5e694d75324 100644 --- a/java/com/android/dialer/app/res/values-mn/strings.xml +++ b/java/com/android/dialer/app/res/values-mn/strings.xml @@ -42,6 +42,8 @@ "Буцааж залгах" "Зурвас" "%1$s: %2$s" + "%s руу залгах" + "Дуут шуудангийн дугаар тодорхойгүй" %1$d Дуут шуудан Дуут шуудан @@ -97,6 +99,11 @@ "Дуут шуудан" "%s сек" "%s минут %s секунд" + "дуут шуудан" + "дуут шуудан" + "Тийм" + "Үгүй" + "Сонгосон %1$s-г устгах уу?" @string/call_log_header_today "%1$s %2$s-д" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Дуудлага" "Дуудлага блоклох" "Дуут шуудан" + + "Дуудлага блоклох тохиргоог түр хугацаагаар унтраасан" "Та сүүлийн 48 цагийн дотор энэ утсаар тусламжийн дуудлага хийсэн тул дуудлага блоклох тохиргоог идэвхгүй болгосон. Энэ тохиргоо нь 48 цагийн хугацаа дуусахад автоматаар идэвхэжнэ." "Импортын тоо" @@ -221,4 +230,6 @@ "Дугаар блокноос гаргах" "Спам" "%1$s офлайн, холбогдох боломжгүй байна" + + diff --git a/java/com/android/dialer/app/res/values-mr/strings.xml b/java/com/android/dialer/app/res/values-mr/strings.xml index 71233ac0ed4b2deb70c92979f62972ceaf9c718f..eb374b9e0e1f099bf1bdd4cfa20d3964c385b44d 100644 --- a/java/com/android/dialer/app/res/values-mr/strings.xml +++ b/java/com/android/dialer/app/res/values-mr/strings.xml @@ -42,6 +42,8 @@ "पुन्हा कॉल करा" "संदेश" "%1$s: %2$s" + "%s डायल करा" + "व्हॉइसमेल नंबर अज्ञात" %1$d व्हॉइसमेल %1$d व्हॉइसमेल @@ -97,6 +99,12 @@ "व्हॉइसमेल" "%s सेकंद" "%s मिनिट %s सेकंद" + "व्हॉइसमेल" + "व्हॉइसमेल" + "होय" + "नाही" + + @string/call_log_header_today "%1$s रोजी %2$s वाजता" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "कॉल" "कॉल अवरोधित करणे" "व्हॉइसमेल" + + "कॉल अवरोधित करणे तात्पुरते बंद" "आपण मागील 48 तासात या फोनवरून आणीबाणी सेवांशी संपर्क साधला असल्याने कॉल अवरोधित करणे अक्षम केले गेले आहे. एकदा 48 तासांचा कालावधी कालबाह्य झाला की ते स्वयंचलितपणे पुन्हा सक्षम केले जाईल." "नंबर अायात करा" @@ -221,4 +231,6 @@ "नंबर अनावरोधित करा" "स्पॅम" "%1$s ऑफलाइन आहे आणि त्यांच्याशी संपर्क साधू शकत नाही" + + diff --git a/java/com/android/dialer/app/res/values-ms/strings.xml b/java/com/android/dialer/app/res/values-ms/strings.xml index 4373c7ca62c221875db3cc06a0890e38cd0c3253..c471ce922ecba3ebd474e00a6b2f97adb8fbdad6 100644 --- a/java/com/android/dialer/app/res/values-ms/strings.xml +++ b/java/com/android/dialer/app/res/values-ms/strings.xml @@ -42,6 +42,10 @@ "Panggil balik" "Mesej" "%1$s: %2$s" + + + + %1$d Mel suara Mel suara @@ -97,6 +101,12 @@ "Mel suara" "%s saat" "%s min %s saat" + "mel suara" + "mel suara" + "Ya" + "Tidak" + + @string/call_log_header_today "%1$s pada %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Panggilan" "Sekatan panggilan" "Mel suara" + + "Sekatan panggilan dimatikan sementara" "Sekatan panggilan telah dilumpuhkan kerana anda menghubungi perkhidmatan kecemasan daripada telefon ini dalam masa 48 jam yang lalu. Ciri ini akan didayakan semula secara automatik apabila tempoh 48 jam berakhir." "Import nombor" @@ -221,4 +233,6 @@ "Nyahsekat nombor" "Spam" "%1$s di luar talian dan tidak dapat dihubungi" + + diff --git a/java/com/android/dialer/app/res/values-my/strings.xml b/java/com/android/dialer/app/res/values-my/strings.xml index fa317bce498c8ad29b1df6e160f72e54fa05a420..dd81dee5f625b258cd25ebedd019fe2480e39626 100644 --- a/java/com/android/dialer/app/res/values-my/strings.xml +++ b/java/com/android/dialer/app/res/values-my/strings.xml @@ -42,6 +42,8 @@ "ပြန်ခေါ်ပါ" "မက်ဆေ့ဂျ်" "%1$s - %2$s" + "%s ကို ခေါ်ပါ" + "အသံမေးလ်နံပါတ် မသိပါ" %1$d အသံမေးလ်များ အသံမေးလ် @@ -97,6 +99,12 @@ "အသံစာပို့စနစ်" "%s စက္ကန့်" "%s မိနစ် %s စက္ကန့်" + "အသံမေးလ်" + "အသံမေးလ်များ" + "Yes" + "No" + + @string/call_log_header_today "%1$s %2$s ၌" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "ခေါ်ဆိုမှုများ" "ခေါ်ဆိုမှု ပိတ်ဆို့ခြင်း" "အသံမေးလ်" + + "ခေါ်ဆိုမှုပိတ်ဆို့ခြင်း ယာယီပိတ်ထားသည်" "သင်သည် လွန်ခဲ့သည့် ၄၈ နာရီအတွင်း ဤဖုန်းဖြင့် အရေးပေါ်ဌာနကိုဖုန်း ခေါ်ဆိုခဲ့သောကြောင့် ခေါ်ဆိုမှုပိတ်ဆို့ခြင်းကို ဖြုတ်ထားသည်။ ၄၈ နာရီကျော်လွန်သည်နှင့် ၎င်းကိုအလိုအလျောက် ပြန်ဖွင့်ပေးပါမည်။" "နံပါတ်များ သွင်းရန်" @@ -221,4 +231,6 @@ "နံပါတ်ကို ဖွင့်မည်" "စပမ်း" "%1$s သည် အော့ဖ်လိုင်းဖြစ်နေသောကြောင့် ဆက်သွယ်၍ မရနိုင်ပါ" + + diff --git a/java/com/android/dialer/app/res/values-nb/strings.xml b/java/com/android/dialer/app/res/values-nb/strings.xml index 488864f3ef74dfa72d56dcf98d0c09cd46dbbd48..8f83c949dc972d970aaf5cd4f39801354d9b1787 100644 --- a/java/com/android/dialer/app/res/values-nb/strings.xml +++ b/java/com/android/dialer/app/res/values-nb/strings.xml @@ -42,6 +42,8 @@ "Ring tilbake" "Melding" "%1$s: %2$s" + "Ring %s" + "Mangler nummer til talepostkasse" %1$d talemeldinger talemelding @@ -97,6 +99,11 @@ "Telefonsvarer" "%s sek" "%s min %s sek" + "talepost" + "talepost" + "Ja" + "Nei" + "Slett markert %1$s?" @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Anrop" "Anropsblokkering" "Talepost" + + "Blokkering av anrop er midlertidig slått av" "Blokkering av anrop er slått av fordi du kontaktet nødtjenester fra denne telefonen i løpet av de siste 48 timene. Funksjonen blir automatisk slått på igjen når perioden på 48 timer er utløpt." "Importér numre" @@ -221,4 +230,6 @@ "Opphev blokkeringen av nummeret" "Nettsøppel" "%1$s er frakoblet og kan ikke nås" + + diff --git a/java/com/android/dialer/app/res/values-ne/strings.xml b/java/com/android/dialer/app/res/values-ne/strings.xml index 33989648eac2f0e1b1da4c2f5cf73cacbb00d4cb..f9524637aaf4b22c43760ac34f9bee95d291dd10 100644 --- a/java/com/android/dialer/app/res/values-ne/strings.xml +++ b/java/com/android/dialer/app/res/values-ne/strings.xml @@ -42,6 +42,8 @@ "फेरि कल गर्नुहोस्" "सन्देश" "%1$s: %2$s" + "%sमा डायल गर्नुहोस्" + "भ्वाइस मेल नम्बर अज्ञात" %1$d भ्वाइसमेलहरू भ्वाइसमेल @@ -97,6 +99,11 @@ "भ्वाइसमेल" "%s सेकेन्ड" "%s मिनेट %s सकेन्ड" + "भ्वाइस मेल" + "भ्वाइस मेलहरू" + "हो" + "होइन" + "चयन गरिएका %1$s लाई मेटाउने हो?" @string/call_log_header_today "%1$s मा %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "कलहरू" "कल रोक्दै" "भ्वाइस मेल" + + "कल अवरुद्ध अस्थायी रुपमा निष्क्रिय" "कल अवरुद्ध अस्थायी रुपमा असक्षम गरिएको छ किनभने तपाईँले अन्तिम ४८ घन्टा भित्र यस फोनबाट आपत्कालीन सेवाहरू सम्पर्क गर्नुभयो। एकपटक ४८ घन्टा अवधि समाप्त भएपछि यो स्वचालित रूपले पुनः सक्रिय हुनेछ।" "नम्बरहरू आयात गर्नुहोस्" @@ -221,4 +230,6 @@ "नम्बरमाथिको रोक हटाउनुहोस्" "स्प्याम" "%1$s अफलाइन हुनुहुन्छ र वहाँलाई भेट्न सकिँदैन" + + diff --git a/java/com/android/dialer/app/res/values-nl/strings.xml b/java/com/android/dialer/app/res/values-nl/strings.xml index 986236e4fc682e46cdfdc1f3d72db2d65598dcc4..49843689782a0a8fa5fce11e4947399f9371f095 100644 --- a/java/com/android/dialer/app/res/values-nl/strings.xml +++ b/java/com/android/dialer/app/res/values-nl/strings.xml @@ -42,6 +42,8 @@ "Terugbellen" "Bericht" "%1$s: %2$s" + "%s bellen" + "Voicemailnummer onbekend" %1$d voicemails Voicemail @@ -97,6 +99,12 @@ "Voicemail" "%s sec." "%s min. %s sec." + "voicemail" + "voicemails" + "Ja" + "Nee" + + @string/call_log_header_today "%1$s om %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Oproepen" "Oproepen blokkeren" "Voicemail" + + "Oproepblokkering tijdelijk uitgeschakeld" "Oproepblokkering is uitgeschakeld omdat je in de afgelopen 48 uur contact met de noodhulpdiensten hebt opgenomen via deze telefoon. De functie wordt automatisch weer ingeschakeld nadat de periode van 48 uur is verstreken." "Nummers importeren" @@ -221,4 +231,6 @@ "Blokkeren van nummer opheffen" "Spam" "%1$s is offline en kan niet worden bereikt" + + diff --git a/java/com/android/dialer/app/res/values-no/strings.xml b/java/com/android/dialer/app/res/values-no/strings.xml index 488864f3ef74dfa72d56dcf98d0c09cd46dbbd48..8f83c949dc972d970aaf5cd4f39801354d9b1787 100644 --- a/java/com/android/dialer/app/res/values-no/strings.xml +++ b/java/com/android/dialer/app/res/values-no/strings.xml @@ -42,6 +42,8 @@ "Ring tilbake" "Melding" "%1$s: %2$s" + "Ring %s" + "Mangler nummer til talepostkasse" %1$d talemeldinger talemelding @@ -97,6 +99,11 @@ "Telefonsvarer" "%s sek" "%s min %s sek" + "talepost" + "talepost" + "Ja" + "Nei" + "Slett markert %1$s?" @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "Anrop" "Anropsblokkering" "Talepost" + + "Blokkering av anrop er midlertidig slått av" "Blokkering av anrop er slått av fordi du kontaktet nødtjenester fra denne telefonen i løpet av de siste 48 timene. Funksjonen blir automatisk slått på igjen når perioden på 48 timer er utløpt." "Importér numre" @@ -221,4 +230,6 @@ "Opphev blokkeringen av nummeret" "Nettsøppel" "%1$s er frakoblet og kan ikke nås" + + diff --git a/java/com/android/dialer/app/res/values-pa/strings.xml b/java/com/android/dialer/app/res/values-pa/strings.xml index 6e9cc03a9bb99428cdd12f0c23a7e6167ca1d634..88e3aa7187300c2383a086fe9bec61daa5e37343 100644 --- a/java/com/android/dialer/app/res/values-pa/strings.xml +++ b/java/com/android/dialer/app/res/values-pa/strings.xml @@ -42,6 +42,8 @@ "ਕਾਲ ਬੈਕ ਕਰੋ" "ਸੁਨੇਹਾ" "%1$s: %2$s" + "%s ਡਾਇਲ ਕਰੋ" + "ਵੌਇਸਮੇਲ ਨੰਬਰ ਅਗਿਆਤ" %1$d ਵੌਇਸਮੇਲਾਂ %1$d ਵੌਇਸਮੇਲਾਂ @@ -97,6 +99,12 @@ "ਵੌਇਸਮੇਲ" "%s ਸਕਿੰਟ" "%s ਮਿੰਟ %s ਸਕਿੰਟ" + "ਵੌਇਸਮੇਲ" + "ਵੌਇਸਮੇਲਾਂ" + "ਹਾਂ" + "ਨਹੀਂ" + + @string/call_log_header_today "%1$s ਨੂੰ %2$s ਵਜੇ" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "ਕਾਲਾਂ" "ਕਾਲ ਬਲੌਕ ਕਰਨਾ" "ਵੌਇਸਮੇਲ" + + "ਕਾਲ ਬਲੌਕਿੰਗ ਆਰਜ਼ੀ ਤੌਰ ਤੇ ਬੰਦ ਹੈ" "ਕਾਲ ਬਲੌਕਿੰਗ ਅਸਮਰੱਥ ਕਰ ਦਿੱਤੀ ਗਈ ਹੈ ਕਿਉਂਕਿ ਤੁਸੀਂ ਇਸ ਫੋਨ ਦੁਆਰਾ ਪਿਛਲੇ 48 ਘੰਟਿਆਂ ਤੋਂ ਐਮਰਜੈਂਸੀ ਸੇਵਾਵਾਂ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਇਹ 48 ਘੰਟਿਆਂ ਦਾ ਸਮਾਂ ਪੂਰਾ ਹੋਣ ਤੇੋਂ ਬਾਅਦ ਆਟੋਮੈਟਿਕਲੀ ਮੁੜ-ਸਮਰੱਥ ਹੋ ਜਾਵੇਗੀ।" "ਆਯਾਤ ਨੰਬਰ" @@ -221,4 +231,6 @@ "ਨੰਬਰ ਨੂੰ ਅਨਬਲੌਕ ਕਰੋ" "ਸਪੈਮ" "%1$s ਔਫਲਾਈਨ ਹੈ ਅਤੇ ਉਸ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ" + + diff --git a/java/com/android/dialer/app/res/values-pl/strings.xml b/java/com/android/dialer/app/res/values-pl/strings.xml index 0c8f43ff6c86f023a4794232555e30d48d20e40e..f408ed353622c21d32bbf9be768b508832329ce6 100644 --- a/java/com/android/dialer/app/res/values-pl/strings.xml +++ b/java/com/android/dialer/app/res/values-pl/strings.xml @@ -42,6 +42,8 @@ "Oddzwoń" "Wyślij SMS-a" "%1$s: %2$s" + "Zadzwoń pod numer %s" + "Numer poczty głosowej jest nieznany" %1$d wiadomości głosowe %1$d wiadomości głosowych @@ -99,6 +101,12 @@ "Poczta głosowa" "%s s" "%s min %s s" + "wiadomości głosowe" + "wiadomości głosowe" + "Tak" + "Nie" + + @string/call_log_header_today "%1$s o %2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Połączenia" "Blokowanie połączeń" "Poczta głosowa" + + "Blokada połączeń tymczasowo wyłączona" "Blokada połączeń została wyłączona, ponieważ w ciągu ostatnich 48 godzin dzwoniono z tego telefonu na numer alarmowy. Blokada zostanie automatycznie przywrócona po upływie 48 godzin." "Zaimportuj numery" @@ -225,4 +235,6 @@ "Odblokuj numer" "Spam" "Użytkownik %1$s jest offline i nie można się z nim skontaktować" + + diff --git a/java/com/android/dialer/app/res/values-pt-rBR/strings.xml b/java/com/android/dialer/app/res/values-pt-rBR/strings.xml index 4f090df6ed483835730f100061078f3b91611254..0fc1da7ac4bc487c8c3bb96cc56ce5993e9bdbfb 100644 --- a/java/com/android/dialer/app/res/values-pt-rBR/strings.xml +++ b/java/com/android/dialer/app/res/values-pt-rBR/strings.xml @@ -42,6 +42,8 @@ "Retornar chamada" "Mensagem" "%1$s: %2$s" + "Discar %s" + "Número do correio de voz desconhecido" %1$d Correios de voz %1$d Correios de voz @@ -97,6 +99,12 @@ "Correio de voz" "%s seg" "%s m %s s" + "correio de voz" + "correios de voz" + "Sim" + "Não" + + @string/call_log_header_today "%1$s às %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Chamadas" "Bloqueio de chamadas" "Correio de voz" + + "Bloqueio de chamadas temporiamente desativado" "O bloqueio de chamadas foi desativado porque você entrou em contato com serviços de emergência usando este telefone nas últimas 48 horas. Ele será reativado automaticamente depois de um período de 48 horas." "Importar números" @@ -221,4 +231,6 @@ "Desbloquear número" "Spam" "%1$s está off-line e não é possível entrar em contato" + + diff --git a/java/com/android/dialer/app/res/values-pt-rPT/strings.xml b/java/com/android/dialer/app/res/values-pt-rPT/strings.xml index 9cabdc4a56430f1401d97cea6b3dbb3f545095f3..f12e25456d93df7ae90812da9d70bcf06203469a 100644 --- a/java/com/android/dialer/app/res/values-pt-rPT/strings.xml +++ b/java/com/android/dialer/app/res/values-pt-rPT/strings.xml @@ -42,6 +42,8 @@ "Ligar de volta" "Mensagem" "%1$s: %2$s" + "Marcar %s" + "Número do correio de voz desconhecido" %1$d mensagens de correio de voz Mensagem de correio de voz @@ -97,6 +99,12 @@ "Correio de voz" "%s seg" "%s min. %s seg." + "mensagem de correio de voz" + "mensagens de correio de voz" + "Sim" + "Não" + + @string/call_log_header_today "%1$s às %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Chamadas" "Bloqueio de chamadas" "Correio de voz" + + "Bloqueio de chamadas tempor. desativado" "O bloqueio de chamadas foi desativado porque contactou os serviços de emergência a partir deste telemóvel nas últimas 48 horas. O bloqueio será automaticamente reativado assim que expirar o período de 48 horas." "Importar números" @@ -221,4 +231,6 @@ "Desbloquear número" "Spam" "%1$s está offline e não pode ser contactado" + + diff --git a/java/com/android/dialer/app/res/values-pt/strings.xml b/java/com/android/dialer/app/res/values-pt/strings.xml index 4f090df6ed483835730f100061078f3b91611254..0fc1da7ac4bc487c8c3bb96cc56ce5993e9bdbfb 100644 --- a/java/com/android/dialer/app/res/values-pt/strings.xml +++ b/java/com/android/dialer/app/res/values-pt/strings.xml @@ -42,6 +42,8 @@ "Retornar chamada" "Mensagem" "%1$s: %2$s" + "Discar %s" + "Número do correio de voz desconhecido" %1$d Correios de voz %1$d Correios de voz @@ -97,6 +99,12 @@ "Correio de voz" "%s seg" "%s m %s s" + "correio de voz" + "correios de voz" + "Sim" + "Não" + + @string/call_log_header_today "%1$s às %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Chamadas" "Bloqueio de chamadas" "Correio de voz" + + "Bloqueio de chamadas temporiamente desativado" "O bloqueio de chamadas foi desativado porque você entrou em contato com serviços de emergência usando este telefone nas últimas 48 horas. Ele será reativado automaticamente depois de um período de 48 horas." "Importar números" @@ -221,4 +231,6 @@ "Desbloquear número" "Spam" "%1$s está off-line e não é possível entrar em contato" + + diff --git a/java/com/android/dialer/app/res/values-ro/strings.xml b/java/com/android/dialer/app/res/values-ro/strings.xml index 3a083ae74e8e6096d3188f5b95fda4e552989f1f..d07dbed8751e454d27bbae9f78507225e47a1649 100644 --- a/java/com/android/dialer/app/res/values-ro/strings.xml +++ b/java/com/android/dialer/app/res/values-ro/strings.xml @@ -42,6 +42,8 @@ "Sunați" "Trimiteți mesaj" "%1$s: %2$s" + "Apelați %s" + "Numărul mesageriei vocale necunoscut" %1$d mesaje vocale %1$d de mesaje vocale @@ -98,6 +100,12 @@ "Mesagerie vocală" "%s secunde" "%s min. %s sec." + "mesagerie vocală" + "mesaje vocale" + "Da" + "Nu" + + @string/call_log_header_today "%1$s la %2$s" "%1$02d:%2$02d" @@ -194,6 +202,8 @@ "Apeluri" "Blocarea apelurilor" "Mesagerie vocală" + + "Blocarea apelurilor e dezactivată temporar" "Blocarea apelurilor a fost dezactivată, deoarece ați contactat serviciile de urgență de pe acest telefon în ultimele 48 de ore. Funcția va fi reactivată automat după ce perioada de 48 de ore va expira." "Importați numere" @@ -223,4 +233,6 @@ "Deblocați numărul" "Spam" "%1$s este offline și nu poate fi contactat(ă)" + + diff --git a/java/com/android/dialer/app/res/values-ru/strings.xml b/java/com/android/dialer/app/res/values-ru/strings.xml index 925d684a5c072e1fc98dc503f23f4fc3cdbed655..e98622de8211d726e1dd33632231fbec4d6edf04 100644 --- a/java/com/android/dialer/app/res/values-ru/strings.xml +++ b/java/com/android/dialer/app/res/values-ru/strings.xml @@ -42,6 +42,8 @@ "Позвонить" "Написать SMS" "%1$s: %2$s" + "Позвонить: %s" + "Номер голосовой почты неизвестен" %1$d голосовое сообщение %1$d голосовых сообщения @@ -99,6 +101,12 @@ "Голосовая почта" "%s сек." "%s мин. %s сек." + "голосовое сообщение" + "голосовые сообщения" + "Да" + "Нет" + + @string/call_log_header_today "%1$s в %2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Вызовы" "Блокировка вызовов" "Голосовая почта" + + "Блокировка вызовов временно отключена" "Блокировка вызовов отключена, поскольку вы недавно набирали номер экстренной службы. Когда с момента звонка пройдет 48 часов, эта функция включится автоматически." "Импортировать номера" @@ -225,4 +235,6 @@ "Разблокировать номер" "Спам" "%1$s сейчас офлайн и не ответит на вызов" + + diff --git a/java/com/android/dialer/app/res/values-si/strings.xml b/java/com/android/dialer/app/res/values-si/strings.xml index 55ce37b819e61bd2c414ea315feaa33bfc726817..c4ae1736d47fb42b704ecf5e9217e00d5a14e004 100644 --- a/java/com/android/dialer/app/res/values-si/strings.xml +++ b/java/com/android/dialer/app/res/values-si/strings.xml @@ -42,6 +42,8 @@ "නැවත අමතන්න" "පණිවිඩය" "%1$s: %2$s" + "%s ඩයල් කරන්න" + "හඬ තැපැල් අංකය නොදනී" හඬ තැපැල් %1$d හඬ තැපැල් %1$d @@ -97,6 +99,12 @@ "හඬ තැපෑල" "තත් %s" "මිනි %s තත් %s" + "හඬ තැපෑල" + "හඬ තැපැල්" + "ඔව්" + "නැත" + + @string/call_log_header_today "%1$s දින %2$sට" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "ඇමතුම්" "ඇමතුම් අවහිර කිරීම" "හඬ තැපෑල" + + "ඇමතුම් අවහිර කිරීම තාවකාලිකව අක්‍රියයි" "ඔබ පසුගිය පැය 48 ඇතුළත මෙම දුරකථනයෙන් හදිසි අවස්ථා සේවා ඇමතූ බැව්න් ඇමතුම් අවහිර කිරීම අබල කර ඇත. පැය 48ක කාල සීමාව ඉකුත් වූ විට එය ස්වයංක්‍රියව යළි සබල කෙරේ." "අංක ආයාත කරන්න" @@ -221,4 +231,6 @@ "අංකය අවහිර නොකරන්න" "අයාචිත තැපෑල" "%1$s නොබැඳි අතර ළඟා වීමට නොහැකිය" + + diff --git a/java/com/android/dialer/app/res/values-sk/strings.xml b/java/com/android/dialer/app/res/values-sk/strings.xml index 59f3d10f1792a1277757adb70ca1b024122b36a6..b5f426938fcd77ae1e2b3740b3fa0e46a6565fb9 100644 --- a/java/com/android/dialer/app/res/values-sk/strings.xml +++ b/java/com/android/dialer/app/res/values-sk/strings.xml @@ -42,6 +42,8 @@ "Zavolať" "Správa" "%1$s: %2$s" + "Vytočiť číslo %s" + "Číslo hlasovej schránky je neznáme" %1$d odkazy v hlasovej schránke %1$d odkazu v hlasovej schránke @@ -99,6 +101,12 @@ "Hlasová schránka" "%s s" "%s min. %s s" + "hlasová správa" + "hlasové správy" + "Áno" + "Nie" + + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Hovory" "Blokovanie hovorov" "Hlasová schránka" + + "Blokovanie hovorov je dočasne vypnuté" "Pretože ste z tohto telefónu počas posledných 48 hodín volali na tiesňovú linku, blokovanie hovorov bolo vypnuté. Po uplynutí 48 hodín sa automaticky znova zapne." "Importovať čísla" @@ -225,4 +235,6 @@ "Zrušiť blokovanie čísla" "Spam" "%1$s je offline a nedá sa zastihnúť" + + diff --git a/java/com/android/dialer/app/res/values-sl/strings.xml b/java/com/android/dialer/app/res/values-sl/strings.xml index 28f4ce021eb624ce67a6ada644987ffeb8faf125..51ac390dea647dcf67d576153c8322dc4dca33e7 100644 --- a/java/com/android/dialer/app/res/values-sl/strings.xml +++ b/java/com/android/dialer/app/res/values-sl/strings.xml @@ -42,6 +42,8 @@ "Povratni klic" "SMS" "%1$s: %2$s" + "Kliči %s" + "Neznana številka odzivnika" %1$d sporočilo v odzivniku %1$d sporočili v odzivniku @@ -99,6 +101,12 @@ "Glasovna pošta" "%s s" "%s min %s s" + "sporočilo v odzivniku" + "sporočila v odzivniku" + "Da" + "Ne" + + @string/call_log_header_today "%1$s ob %2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Klici" "Blokiranje klicev" "Odzivnik" + + "Blokiranje klicev je začasno izklopljeno" "Blokiranje klicev je onemogočeno, ker ste se v zadnjih 48 urah s tem telefonom obrnili na nujno pomoč. Ko 48-urno obdobje poteče, bo blokiranje klicev samodejno znova omogočeno." "Uvoz številk" @@ -225,4 +235,6 @@ "Odblokiranje telefonske številke" "Vsiljena pošta" "Oseba %1$s nima vzpostavljene povezave in ni dosegljiva" + + diff --git a/java/com/android/dialer/app/res/values-sq/strings.xml b/java/com/android/dialer/app/res/values-sq/strings.xml index 48ec8fee881c1d1c76f0de552d7ca6ec5499640b..8bc3e85be39b3a83478650cbec26041279a3c121 100644 --- a/java/com/android/dialer/app/res/values-sq/strings.xml +++ b/java/com/android/dialer/app/res/values-sq/strings.xml @@ -42,6 +42,10 @@ "Telefono" "Mesazh" "%1$s: %2$s" + + + + %1$d posta zanore postë zanore @@ -97,6 +101,12 @@ "Posta zanore" "%s sekonda" "%s min. e %s sek." + "posta zanore" + "postat zanore" + "Po" + "Jo" + + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Telefonatat" "Bllokimi i telefonatave" "Posta zanore" + + "Bllokimi i telefonatave është përkohësisht joaktiv" "Bllokimi i telefonatave është çaktivizuar sepse kontaktove me shërbimet e urgjencës nga ky telefon brenda 48 orëve të fundit. Ai do të riaktivizohet automatikisht pas skadimit të periudhës prej 48 orë." "Importo numrat" @@ -221,4 +233,6 @@ "Zhblloko numrin" "E bezdisshme" "%1$s është jashtë linje dhe nuk mund të kontaktohet" + + diff --git a/java/com/android/dialer/app/res/values-sr/strings.xml b/java/com/android/dialer/app/res/values-sr/strings.xml index fd4e2b9bad0faf222ba9f3aef6f680c2438243f8..e7f7f912d4b387fa1ba2182147002d92713143fd 100644 --- a/java/com/android/dialer/app/res/values-sr/strings.xml +++ b/java/com/android/dialer/app/res/values-sr/strings.xml @@ -42,6 +42,8 @@ "Узврати позив" "Пошаљи SMS" "%1$s: %2$s" + "Позови %s" + "Непознат број говорне поште" %1$d говорна порука %1$d говорне поруке @@ -98,6 +100,12 @@ "Говорна пошта" "%s сек" "%s мин %s сек" + "говорну поруку" + "говорне поруке" + "Да" + "Не" + + @string/call_log_header_today "%1$s у %2$s" "%1$02d:%2$02d" @@ -194,6 +202,8 @@ "Позиви" "Блокирање позива" "Говорна пошта" + + "Блокирање позива је привремено искључено" "Блокирање позива је онемогућено зато што сте контактирали службе за помоћ у хитним случајевима са овог телефона у последњих 48 сати. Аутоматски ће бити поново омогућено када истекне период од 48 сати." "Увези бројеве" @@ -223,4 +233,6 @@ "Деблокирај број" "Непожељан" "%1$s је офлајн и не можете да га/је контактирате" + + diff --git a/java/com/android/dialer/app/res/values-sv/strings.xml b/java/com/android/dialer/app/res/values-sv/strings.xml index fc8920a3841e64da50fbf281bfc4abe6d527f0c0..36616ce832629d851d145f6ed3d0734b54968bb3 100644 --- a/java/com/android/dialer/app/res/values-sv/strings.xml +++ b/java/com/android/dialer/app/res/values-sv/strings.xml @@ -42,6 +42,8 @@ "Ring upp" "Meddelande" "%1$s: %2$s" + "Ring %s" + "Numret till röstbrevlådan är okänt" %1$d röstmeddelanden röstmeddelande @@ -97,6 +99,12 @@ "Röstbrevlåda" "%s sekund" "%s min %s sek" + "röstbrevlåda" + "röstmeddelanden" + "Ja" + "Nej" + + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Samtal" "Samtalsblockering" "Röstbrevlåda" + + "Blockeringen har inaktiverats tillfälligt" "Samtalsblockering har inaktiverats eftersom du ringde ett larmnummer från den här mobilen under de senaste 48 timmarna. Blockeringen aktiveras igen när 48 timmar har gått." "Importera nummer" @@ -221,4 +231,6 @@ "Häv blockeringen av numret" "Spam" "%1$s är offline och går inte att nå" + + diff --git a/java/com/android/dialer/app/res/values-sw/strings.xml b/java/com/android/dialer/app/res/values-sw/strings.xml index 4c469979a41afb795b4271d310ecae172ed2af05..fdbdd7d02735a0f25f6f09c3e7854f7c9a8cdf79 100644 --- a/java/com/android/dialer/app/res/values-sw/strings.xml +++ b/java/com/android/dialer/app/res/values-sw/strings.xml @@ -42,6 +42,10 @@ "Mpigie" "Ujumbe" "%1$s: %2$s" + + + + Ujumbe %1$d wa sauti Ujumbe wa sauti @@ -97,6 +101,12 @@ "Ujumbe wa sauti" "Sekunde %s" "Dak %s sek %s" + "ujumbe wa sauti" + "ujumbe wa sauti" + "Ndiyo" + "Hapana" + + @string/call_log_header_today "%1$s saa %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Simu zilizopigwa" "Kuzuia simu" "Ujumbe wa sauti" + + "Kuzuia simu kumezimwa kwa muda" "Kipengele cha kuzuia simu kimezimwa kwa sababu uliwasiliana na huduma za dharura kwenye simu hii ndani ya saa 48 zilizopita. Kipengele hiki kitawashwa kiotomatiki baada ya kipindi cha saa 48 kumalizika." "Leta nambari" @@ -221,4 +233,6 @@ "Ondolea nambari kizuizi" "Taka" "%1$s hayuko mtandaoni na hapatikani" + + diff --git a/java/com/android/dialer/app/res/values-ta/strings.xml b/java/com/android/dialer/app/res/values-ta/strings.xml index 0b5a51d9f2d12eea4edea8dcf1e536f28f6dd5b0..f7e1d19c4413490be25027817e36567d3f650def 100644 --- a/java/com/android/dialer/app/res/values-ta/strings.xml +++ b/java/com/android/dialer/app/res/values-ta/strings.xml @@ -42,6 +42,8 @@ "அழை" "செய்தி அனுப்பு" "%1$s: %2$s" + "%s என்ற எண்ணை அழைக்கவும்" + "குரலஞ்சல் எண் அறியப்படவில்லை" %1$d குரலஞ்சல்கள் குரலஞ்சல் @@ -97,6 +99,12 @@ "குரலஞ்சல்" "%s வி" "%s நிமிடம் %s வினாடி" + "குரலஞ்சல்" + "குரலஞ்சல்கள்" + "ஆம்" + "வேண்டாம்" + + @string/call_log_header_today "%1$s அன்று %2$s மணிக்கு" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "அழைப்புகள்" "அழைப்புத் தடுப்பு" "குரலஞ்சல்" + + "அழைப்புத் தடுப்பு அம்சம் தற்காலிகமாக முடக்கப்பட்டுள்ளது" "கடந்த 48 மணிநேரத்தில், இந்த ஃபோனிலிருந்து அவசர அழைப்பு எண்ணைத் தொடர்புகொண்டதால் அழைப்புத் தடுப்பு அம்சம் முடக்கப்பட்டுள்ளது. 48 மணிநேரம் கழித்து, இந்த அம்சம் தானாகவே மீண்டும் இயக்கப்படும்." "எண்களை இறக்கு" @@ -221,4 +231,6 @@ "எண்ணை அனுமதி" "ஸ்பேம்" "%1$s ஆஃப்லைனில் உள்ளதால், தொடர்புகொள்ள முடியாது" + + diff --git a/java/com/android/dialer/app/res/values-te/strings.xml b/java/com/android/dialer/app/res/values-te/strings.xml index 512f7e2761b7e470f5b8ed1668d732921da4f266..babfb9a1e9fc444998a2cc80025e3213ab7d4dd4 100644 --- a/java/com/android/dialer/app/res/values-te/strings.xml +++ b/java/com/android/dialer/app/res/values-te/strings.xml @@ -42,6 +42,8 @@ "కాల్ చేయి" "సందేశం పంపు" "%1$s: %2$s" + "%sకు డయల్ చేయండి" + "వాయిస్ మెయిల్ నంబర్ తెలియదు" %1$d వాయిస్ మెయిల్‌లు వాయిస్ మెయిల్ @@ -97,6 +99,12 @@ "వాయిస్ మెయిల్" "%s సెక" "%s నిమి %s సెక" + "వాయిస్ మెయిల్" + "వాయిస్ మెయిల్‌లు" + "అవును" + "వద్దు" + + @string/call_log_header_today "%1$s %2$sకి" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "కాల్‌లు" "కాల్ బ్లాక్ చేయడం" "వాయిస్ మెయిల్" + + "కాల్ బ్లాకింగ్ తాత్కాలికంగా ఆఫ్ అయ్యింది" "మీరు గత 48 గంటల వ్యవధిలో ఈ ఫోన్ నుండి అత్యవసర సేవలను సంప్రదించినందున కాల్ బ్లాకింగ్ నిలిపివేయబడింది. 48 గంటల వ్యవధి ముగిసిన తర్వాత ఇది స్వయంచాలకంగా పునఃప్రారంభించబడుతుంది." "నంబర్‌లను దిగుమతి చేయి" @@ -221,4 +231,6 @@ "నంబర్‌ను అన్‌బ్లాక్ చేయి" "స్పామ్" "%1$s ఆఫ్‌లైన్‌లో ఉన్నందున వారిని చేరుకోవడం సాధ్యపడదు" + + diff --git a/java/com/android/dialer/app/res/values-th/strings.xml b/java/com/android/dialer/app/res/values-th/strings.xml index 6817d51b814e41428f0ea5eafed182a3bb77ebb7..4c2fd37b254c14505bbfe3acf1a084ecbc8499e8 100644 --- a/java/com/android/dialer/app/res/values-th/strings.xml +++ b/java/com/android/dialer/app/res/values-th/strings.xml @@ -42,6 +42,8 @@ "โทรกลับ" "ข้อความ" "%1$s: %2$s" + "หมุนหมายเลข %s" + "ไม่ทราบหมายเลขข้อความเสียง" %1$d ข้อความเสียง ข้อความเสียง @@ -97,6 +99,12 @@ "ข้อความเสียง" "%s วินาที" "%s นาที %s วินาที" + "ข้อความเสียง" + "ข้อความเสียง" + "ใช่" + "ไม่" + + @string/call_log_header_today "วันที่ %1$s เวลา %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "การโทร" "การบล็อกสายเรียกเข้า" "ข้อความเสียง" + + "การบล็อกสายเรียกเข้าปิดชั่วคราว" "ระบบปิดใช้การบล็อกสายเรียกเข้าเนื่องจากคุณติดต่อบริการฉุกเฉินจากโทรศัพท์เครื่องนี้ภายใน 48 ชั่วโมงที่ผ่านมา ระบบจะเปิดใช้คุณลักษณะนี้อีกครั้งโดยอัตโนมัติเมื่อครบ 48 ชั่วโมง" "นำเข้าหมายเลข" @@ -221,4 +231,6 @@ "เลิกบล็อกหมายเลข" "สแปม" "%1$s ออฟไลน์อยู่และไม่สามารถติดต่อได้" + + diff --git a/java/com/android/dialer/app/res/values-tl/strings.xml b/java/com/android/dialer/app/res/values-tl/strings.xml index c98a04633cf6982389c50fdf243bde69af6ee1e6..6afb11c1d3f670f05c32da6928ca4aaa735b4aa2 100644 --- a/java/com/android/dialer/app/res/values-tl/strings.xml +++ b/java/com/android/dialer/app/res/values-tl/strings.xml @@ -42,6 +42,8 @@ "Tawagan" "Mensahe" "%1$s: %2$s" + "I-dial ang %s" + "Hindi kilala ang numero ng voicemail" %1$d Voicemail %1$d na Voicemail @@ -97,6 +99,12 @@ "Voicemail" "%s sec" "%s min %s sec" + "voicemail" + "mga voicemail" + "Oo" + "Hindi" + + @string/call_log_header_today "%1$s ng %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Mga Tawag" "Pagba-block ng tawag" "Voicemail" + + "Pansamantalang na-off ang call blocking" "Na-disable ang pagba-block ng tawag dahil nakipag-ugnayan ka sa mga pang-emergency na serbisyo mula sa teleponong ito sa nakalipas na 48 oras. Awtomatiko itong muling i-enable kapag nag-expire na ang 48 oras." "I-import ang mga numero" @@ -221,4 +231,6 @@ "Alisin sa pagkaka-block ang numero" "Spam" "Offline si %1$s at hindi makontak" + + diff --git a/java/com/android/dialer/app/res/values-tr/strings.xml b/java/com/android/dialer/app/res/values-tr/strings.xml index 73b3cd729fad3556a3fb141b6d1170cbd771937b..8b30d4bff30b5d5f7440f58fe11841b6aeee5aa0 100644 --- a/java/com/android/dialer/app/res/values-tr/strings.xml +++ b/java/com/android/dialer/app/res/values-tr/strings.xml @@ -42,6 +42,10 @@ "Geri ara" "İleti" "%1$s: %2$s" + + + + %1$d Sesli Mesaj Sesli Mesaj @@ -97,6 +101,12 @@ "Sesli Mesaj" "%s sn." "%s dk. %s sn." + "sesli mesaj" + "sesli mesajlar" + "Evet" + "Hayır" + + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Çağrılar" "Çağrı engelleme" "Sesli mesaj" + + "Çağrı engelleme geçici olarak kapalı" "Son 48 saat içinde bu telefondan acil servislerle iletişimde bulunduğunuz için çağrı engelleme modu devre dışı bırakıldı. 48 saatlik süre dolduktan sonra çağrı engelleme modu otomatik olarak tekrar etkinleştirilecektir." "Numaraları içe aktar" @@ -221,4 +233,6 @@ "Numaranın engellemesini kaldır" "Spam" "%1$s çevrimdışı olduğundan ulaşılamıyor" + + diff --git a/java/com/android/dialer/app/res/values-uk/strings.xml b/java/com/android/dialer/app/res/values-uk/strings.xml index dd768909398d7f2efe8c76a0102160fbdaff91eb..f1c5b3f37164ca00d8a4d460bda251385b232cfe 100644 --- a/java/com/android/dialer/app/res/values-uk/strings.xml +++ b/java/com/android/dialer/app/res/values-uk/strings.xml @@ -42,6 +42,8 @@ "Передзвонити" "Повідомлення" "%1$s: %2$s" + "Набрати %s" + "Невідомий номер голосової пошти" %1$d голосове повідомлення %1$d голосові повідомлення @@ -99,6 +101,12 @@ "Голосова пошта" "%s с" "%s хв %s с" + "голосова пошта" + "голосова пошта" + "Так" + "Ні" + + @string/call_log_header_today "%1$s о %2$s" "%1$02d:%2$02d" @@ -196,6 +204,8 @@ "Дзвінки" "Блокування викликів" "Голосова пошта" + + "Блокування дзвінків тимчасово вимкнено" "Блокування дзвінків вимкнено, оскільки ви зверталися з цього телефона в екстрені служби протягом останніх 48 годин. Ця функція автоматично ввімкнеться, коли мине 48 годин." "Імпортувати номери" @@ -225,4 +235,6 @@ "Розблокувати номер" "Спам" "%1$s не в мережі, неможливо встановити зв’язок" + + diff --git a/java/com/android/dialer/app/res/values-ur/strings.xml b/java/com/android/dialer/app/res/values-ur/strings.xml index 534b915ccda43d95e3b18b2a86a08ea0caf9d35a..b212812889599ea2b1367bf056a7dd188e62c605 100644 --- a/java/com/android/dialer/app/res/values-ur/strings.xml +++ b/java/com/android/dialer/app/res/values-ur/strings.xml @@ -42,6 +42,10 @@ "واپس کال کریں" "پیغام" "%1$s: %2$s" + + + + %1$d صوتی میلز صوتی میل @@ -97,6 +101,12 @@ "صوتی میل" "%s سیکنڈ" "%s منٹ %s سیکنڈ" + "صوتی میل" + "صوتی میلز" + "ہاں" + "نہیں" + + @string/call_log_header_today "%1$s بوقت %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "کالز" "کال مسدود کرنا" "صوتی میل" + + "کال مسدود کرنا عارضی طور پر آف ہے" "کال مسدود کرنا غیر فعال کر دیا گیا ہے کیونکہ آپ نے پچھلے 48 گھنٹوں میں اس فون سے ہنگامی سروسز کے ساتھ رابطہ کیا تھا۔ جب 48 گھنٹے کا دورانیہ ختم ہوگا تو یہ خودکار طور پر دوبارہ فعال ہو جائے گا۔" "نمبرز درآمد کریں" @@ -221,4 +233,6 @@ "نمبر غیر مسدود کریں" "سپام" "%1$s آف لائن ہے اور اس تک پہنچا نہیں جا سکتا" + + diff --git a/java/com/android/dialer/app/res/values-uz/strings.xml b/java/com/android/dialer/app/res/values-uz/strings.xml index 11befbc5197e2d97404705afff42516743fc124f..e52d2bdf7b07014f3cd7caf57b719a039a30ac5c 100644 --- a/java/com/android/dialer/app/res/values-uz/strings.xml +++ b/java/com/android/dialer/app/res/values-uz/strings.xml @@ -42,6 +42,10 @@ "Telefon" "SMS yozish" "%1$s: %2$s" + + + + %1$d ta ovozli xabar Ovozli xabar @@ -97,6 +101,12 @@ "Ovozli pochta" "%s soniya" "%s daq %s son" + "ovozli xabar" + "ovozli xabarlar" + "Ha" + "Yo‘q" + + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "Chaqiruvlar" "Qo‘ng‘iroqlarni bloklash" "Ovozli pochta" + + "Qo‘ng‘iroqlarni bloklash o‘chirilgan" "Oxirgi 48 soat ichida ushbu telefon orqali favqulodda xizmatlar bilan bog‘lanilganligi uchun qo‘ng‘iroqlarni bloklash o‘chirib qo‘yildi. 48 soatlik muddat tugagandan so‘ng bu avtomatik qayta yoqiladi." "Raqamlarni import qilish" @@ -221,4 +233,6 @@ "Raqamni blokdan chiqarish" "Spam" "%1$s hozir oflayn va u bilan bog‘lanishning imkoni yo‘q" + + diff --git a/java/com/android/dialer/app/res/values-vi/strings.xml b/java/com/android/dialer/app/res/values-vi/strings.xml index 942f0676869206c4664c4e9ea757a9267d026252..66b3468540255b4c19fb73027204132860367947 100644 --- a/java/com/android/dialer/app/res/values-vi/strings.xml +++ b/java/com/android/dialer/app/res/values-vi/strings.xml @@ -42,6 +42,8 @@ "Gọi lại" "Tin nhắn" "%1$s: %2$s" + "Quay số %s" + "Số thư thoại không xác định" %1$d Thư thoại Thư thoại @@ -97,6 +99,12 @@ "Thư thoại" "%s giây" "%s phút %s giây" + "thư thoại" + "thư thoại" + "Có" + "Không" + + @string/call_log_header_today "%1$s lúc %2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Cuộc gọi" "Chặn cuộc gọi" "Thư thoại" + + "Tạm thời tắt chặn cuộc gọi" "Tính năng chặn cuộc gọi đã bị tắt vì bạn đã liên hệ với dịch vụ khẩn cấp từ điện thoại này trong vòng 48 giờ qua. Tính năng này sẽ được bật lại tự động sau khi khoảng thời gian 48 giờ kết thúc." "Nhập số" @@ -221,4 +231,6 @@ "Bỏ chặn số" "Spam" "%1$s ngoại tuyến và không liên hệ được" + + diff --git a/java/com/android/dialer/app/res/values-zh-rCN/strings.xml b/java/com/android/dialer/app/res/values-zh-rCN/strings.xml index 4b6f55a69de13d8a9ac0a751c74d69377a3c7bae..c64234e22d6c6db98d60d0a9c0782d312644fae5 100644 --- a/java/com/android/dialer/app/res/values-zh-rCN/strings.xml +++ b/java/com/android/dialer/app/res/values-zh-rCN/strings.xml @@ -42,6 +42,8 @@ "回拨" "发短信" "%1$s%2$s" + "拨打 %s" + "语音信箱号码未知" %1$d 封语音邮件 1 封语音邮件 @@ -97,6 +99,12 @@ "语音信箱" "%s 秒" "%s 分钟 %s 秒" + "语音邮件" + "语音邮件" + "是" + "否" + + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "通话" "来电屏蔽" "语音邮件" + + "来电拦截功能已暂时关闭" "来电拦截功能已停用,因为您在过去 48 小时内使用该手机拨打了紧急服务电话。系统会在 48 小时的期限结束后自动重新启用该功能。" "导入号码" @@ -221,4 +231,6 @@ "取消屏蔽号码" "骚扰电话号码" "%1$s不在线,无法接通" + + diff --git a/java/com/android/dialer/app/res/values-zh-rHK/strings.xml b/java/com/android/dialer/app/res/values-zh-rHK/strings.xml index 95dd238710c2652c696f436601d28d79f17d3a24..693e56caa7006432c71ddb5d3b1f0c8177b6c462 100644 --- a/java/com/android/dialer/app/res/values-zh-rHK/strings.xml +++ b/java/com/android/dialer/app/res/values-zh-rHK/strings.xml @@ -42,6 +42,8 @@ "回撥" "短訊" "%1$s%2$s" + "撥號 %s" + "沒有可用的留言信箱號碼" %1$d 個留言 留言 @@ -97,6 +99,11 @@ "留言" "%s 秒" "%s%s 秒" + "留言" + "留言" + "是" + "否" + "要刪除所選的%1$s嗎?" @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" @@ -192,6 +199,8 @@ "通話" "來電封鎖" "留言" + + "暫時關閉來電封鎖功能" "您在過去 48 小時內曾經使用此手機聯絡緊急服務,因此來電封鎖功能已停用。系統會在 48 小時期限結束後自動重新啟用功能。" "匯入號碼" @@ -221,4 +230,6 @@ "解除封鎖號碼" "垃圾號碼" "%1$s已離線,無法取得聯繫" + + diff --git a/java/com/android/dialer/app/res/values-zh-rTW/strings.xml b/java/com/android/dialer/app/res/values-zh-rTW/strings.xml index 66d986d8cb3dc5c00a13f44354bb40892a60dcf5..3675d3f0999dcfc8cd095dd4b50eb6dfb193dfec 100644 --- a/java/com/android/dialer/app/res/values-zh-rTW/strings.xml +++ b/java/com/android/dialer/app/res/values-zh-rTW/strings.xml @@ -42,6 +42,10 @@ "回撥" "傳送簡訊" "%1$s%2$s" + + + + %1$d 則語音留言 語音留言 @@ -97,6 +101,12 @@ "語音留言" "%s 秒" "%s%s 秒" + "語音留言" + "語音留言" + "是" + "否" + + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" @@ -192,6 +202,8 @@ "通話" "來電封鎖" "語音留言" + + "來電封鎖功能已暫時關閉" "由於您曾在過去 48 小時內使用這支手機撥打緊急服務電話,因此來電封鎖功能已停用。此功能停用達 48 小時後,將由系統自動重新啟用。" "匯入電話號碼" @@ -221,4 +233,6 @@ "解除封鎖號碼" "騷擾/廣告電話" "%1$s已離線,無法接聽來電" + + diff --git a/java/com/android/dialer/app/res/values-zu/strings.xml b/java/com/android/dialer/app/res/values-zu/strings.xml index 4cee09247e676b43f9eec467fbf63ee48bfe46b2..0d9957dda5c4a388ede6f4f6b8b5c7a7519094b1 100644 --- a/java/com/android/dialer/app/res/values-zu/strings.xml +++ b/java/com/android/dialer/app/res/values-zu/strings.xml @@ -42,6 +42,8 @@ "Phinda ushaye" "Umlayezo" "%1$s: %2$s" + "Dayela %s" + "Inombolo yevoyisimeyili ayaziwa" %1$d Amavoyisimeyili %1$d Amavoyisimeyili @@ -97,6 +99,12 @@ "Ivoyisimeyili" "%s isekhondi" "%s amaminithi %s amasekhondi" + "ivoyisimeyili" + "ama-meyli ezwi" + "Yebo" + "Cha" + + @string/call_log_header_today "%1$s ngo-%2$s" "%1$02d:%2$02d" @@ -192,6 +200,8 @@ "Amakholi" "Ukuvimbela ikholi" "Ivoyisimeyili" + + "Ukuvimbela ikholi kuvalwe isikhashana" "Ukuvimbela ikholi kukhutshaziwe ngoba uxhumane nabosizo oluphuthumayo kusukela kule foni phakathi kwamahora angu-48 wokugcina. Kuzophinda kunikwe amandla ngokuzenzakalela uma sokuphele isikhathi samahora angu-48." "Ngenisa izinombolo" @@ -221,4 +231,6 @@ "Vulela inombolo" "Ugaxekile" "U-%1$s akaxhunyiwe kwi-inthanethi futhi akakwazi ukufinyelelwa" + + diff --git a/java/com/android/dialer/app/res/values/strings.xml b/java/com/android/dialer/app/res/values/strings.xml index 9944f9ff26cd1da945e00dae239c016bf10a6211..9e1fdeb5a57a03bf7536db4cf69ca7155f4325d5 100644 --- a/java/com/android/dialer/app/res/values/strings.xml +++ b/java/com/android/dialer/app/res/values/strings.xml @@ -105,6 +105,12 @@ %1$s: %2$s + + Dial %s + + Voicemail number unknown Voicemail @@ -356,6 +362,12 @@ %s min %s sec + voicemail + voicemails + Yes + No + Delete selected %1$s? + @@ -752,6 +764,9 @@ Voicemail + + Select SIM for voicemail settings + @@ -882,4 +897,7 @@ %1$s is offline and can\'t be reached + + About + diff --git a/java/com/android/dialer/app/res/values/styles.xml b/java/com/android/dialer/app/res/values/styles.xml index 3b2df96f23c3aa45e06c32034f3894db2f26e558..7adf7ca2c5f32b52dae2d61618f9690f6f1dbae5 100644 --- a/java/com/android/dialer/app/res/values/styles.xml +++ b/java/com/android/dialer/app/res/values/styles.xml @@ -142,6 +142,8 @@ 0dp + + diff --git a/java/com/android/incallui/video/impl/res/values-w460dp-land/dimens.xml b/java/com/android/incallui/video/impl/res/values-w460dp-land/dimens.xml new file mode 100644 index 0000000000000000000000000000000000000000..ac2d0316af7023197643ef021fcc07f54d5f647d --- /dev/null +++ b/java/com/android/incallui/video/impl/res/values-w460dp-land/dimens.xml @@ -0,0 +1,19 @@ + + + + 116dp + diff --git a/java/com/android/incallui/video/impl/res/values-w460dp/dimens.xml b/java/com/android/incallui/video/impl/res/values-w460dp/dimens.xml index b1a86a0fa454e4cf81140a28708dbfa696831be1..a53fb64043ff1313602dfe391676b2a075ff02cc 100644 --- a/java/com/android/incallui/video/impl/res/values-w460dp/dimens.xml +++ b/java/com/android/incallui/video/impl/res/values-w460dp/dimens.xml @@ -1,7 +1,23 @@ + 16dp 72dp 88dp 88dp + 104dp diff --git a/java/com/android/incallui/video/impl/res/values/dimens.xml b/java/com/android/incallui/video/impl/res/values/dimens.xml index 45860036fcbb893bc7636e247c26ae3784e1fda7..aa08c9d6d0d15b609593fef3039cc5800b4e9f39 100644 --- a/java/com/android/incallui/video/impl/res/values/dimens.xml +++ b/java/com/android/incallui/video/impl/res/values/dimens.xml @@ -1,7 +1,23 @@ + 72dp 72dp + 84dp 24dp 24dp 24dp diff --git a/java/com/android/incallui/video/impl/res/values/styles.xml b/java/com/android/incallui/video/impl/res/values/styles.xml index b94400875b2bab95b70b39b797ccb698d52001e5..f73075f094cc3e29123551782fcc147a6f66db4b 100644 --- a/java/com/android/incallui/video/impl/res/values/styles.xml +++ b/java/com/android/incallui/video/impl/res/values/styles.xml @@ -1,6 +1,20 @@ + - + diff --git a/java/com/android/incallui/video/protocol/AndroidManifest.xml b/java/com/android/incallui/video/protocol/AndroidManifest.xml index 3a1dfb7a9f297bcdb75dc5944b57e96a6a307c24..cfb6b27ad590a26817d0fe2e3ab5483f0c758def 100644 --- a/java/com/android/incallui/video/protocol/AndroidManifest.xml +++ b/java/com/android/incallui/video/protocol/AndroidManifest.xml @@ -18,5 +18,5 @@ package="com.android.incallui.video.protocol"> + android:targetSdkVersion="26"/> \ No newline at end of file diff --git a/java/com/android/incallui/videosurface/impl/VideoSurfaceTextureImpl.java b/java/com/android/incallui/videosurface/impl/VideoSurfaceTextureImpl.java index 21160cadba8e1566b6e92086b3df1926b1b8bc52..8cac402292ec7304dd9cc349cda50461969e0904 100644 --- a/java/com/android/incallui/videosurface/impl/VideoSurfaceTextureImpl.java +++ b/java/com/android/incallui/videosurface/impl/VideoSurfaceTextureImpl.java @@ -96,8 +96,7 @@ public class VideoSurfaceTextureImpl implements VideoSurfaceTexture { if (this.textureView != null) { this.textureView.setOnClickListener(null); - // Don't clear the surface texture listener. This is important because our listener prevents - // the surface from being released so that it can be reused later. + this.textureView.setSurfaceTextureListener(null); } this.textureView = textureView; @@ -137,12 +136,12 @@ public class VideoSurfaceTextureImpl implements VideoSurfaceTexture { LogUtil.i( "VideoSurfaceTextureImpl.createSurface", "width: " + width + ", height: " + height + " " + toString()); - if (savedSurfaceTexture != null) { - savedSurfaceTexture.setDefaultBufferSize(width, height); - savedSurface = new Surface(savedSurfaceTexture); - return true; + savedSurfaceTexture.setDefaultBufferSize(width, height); + if (savedSurface != null) { + savedSurface.release(); } - return false; + savedSurface = new Surface(savedSurfaceTexture); + return true; } private void onSurfaceCreated() { diff --git a/java/com/android/incallui/videotech/VideoTech.java b/java/com/android/incallui/videotech/VideoTech.java index 39998ad4c8f59e30807045752d4d98be28192e77..7da74c057be6fa51b86d0858aad5deed7f67420e 100644 --- a/java/com/android/incallui/videotech/VideoTech.java +++ b/java/com/android/incallui/videotech/VideoTech.java @@ -78,5 +78,7 @@ public interface VideoTech { void onPeerDimensionsChanged(int width, int height); void onVideoUpgradeRequestReceived(); + + void onUpgradedToVideo(boolean switchToSpeaker); } } diff --git a/java/com/android/incallui/videotech/ims/ImsVideoCallCallback.java b/java/com/android/incallui/videotech/ims/ImsVideoCallCallback.java index 9b5222e10fe45c6fb9e787716c9f5ddb8abfc3fd..17c2e65182a6c220ae08a0b1a3798e5d210ec722 100644 --- a/java/com/android/incallui/videotech/ims/ImsVideoCallCallback.java +++ b/java/com/android/incallui/videotech/ims/ImsVideoCallCallback.java @@ -24,6 +24,8 @@ import android.telecom.InCallService.VideoCall; import android.telecom.VideoProfile; import android.telecom.VideoProfile.CameraCapabilities; import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.LoggingBindings; import com.android.incallui.videotech.VideoTech.VideoTechListener; import com.android.incallui.videotech.utils.SessionModificationState; @@ -31,12 +33,18 @@ import com.android.incallui.videotech.utils.SessionModificationState; public class ImsVideoCallCallback extends VideoCall.Callback { private static final int CLEAR_FAILED_REQUEST_TIMEOUT_MILLIS = 4000; private final Handler handler = new Handler(); + private final LoggingBindings logger; private final Call call; private final ImsVideoTech videoTech; private final VideoTechListener listener; private int requestedVideoState = VideoProfile.STATE_AUDIO_ONLY; - ImsVideoCallCallback(final Call call, ImsVideoTech videoTech, VideoTechListener listener) { + ImsVideoCallCallback( + final LoggingBindings logger, + final Call call, + ImsVideoTech videoTech, + VideoTechListener listener) { + this.logger = logger; this.call = call; this.videoTech = videoTech; this.listener = listener; @@ -61,6 +69,7 @@ public class ImsVideoCallCallback extends VideoCall.Callback { videoTech.setSessionModificationState( SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST); listener.onVideoUpgradeRequestReceived(); + logger.logImpression(DialerImpression.Type.IMS_VIDEO_REQUEST_RECEIVED); } } @@ -87,7 +96,10 @@ public class ImsVideoCallCallback extends VideoCall.Callback { handler.removeCallbacksAndMessages(null); // Clear everything final int newSessionModificationState = getSessionModificationStateFromTelecomStatus(status); - if (status != VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS) { + if (status == VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS) { + // Telecom manages audio route for us + listener.onUpgradedToVideo(false /* switchToSpeaker */); + } else { // This will update the video UI to display the error message. videoTech.setSessionModificationState(newSessionModificationState); } diff --git a/java/com/android/incallui/videotech/ims/ImsVideoTech.java b/java/com/android/incallui/videotech/ims/ImsVideoTech.java index 66a7af58a9e0c5e3fe79494763985a90323d9cb3..363a193972e96704e93ad86a2827c402fe4df9d8 100644 --- a/java/com/android/incallui/videotech/ims/ImsVideoTech.java +++ b/java/com/android/incallui/videotech/ims/ImsVideoTech.java @@ -23,6 +23,8 @@ import android.telecom.Call.Details; import android.telecom.VideoProfile; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.LoggingBindings; import com.android.incallui.video.protocol.VideoCallScreen; import com.android.incallui.video.protocol.VideoCallScreenDelegate; import com.android.incallui.videotech.VideoTech; @@ -30,14 +32,17 @@ import com.android.incallui.videotech.utils.SessionModificationState; /** ViLTE implementation */ public class ImsVideoTech implements VideoTech { + private final LoggingBindings logger; private final Call call; private final VideoTechListener listener; private ImsVideoCallCallback callback; private @SessionModificationState int sessionModificationState = SessionModificationState.NO_REQUEST; private int previousVideoState = VideoProfile.STATE_AUDIO_ONLY; + private boolean paused = false; - public ImsVideoTech(VideoTechListener listener, Call call) { + public ImsVideoTech(LoggingBindings logger, VideoTechListener listener, Call call) { + this.logger = logger; this.listener = listener; this.call = call; } @@ -87,7 +92,7 @@ public class ImsVideoTech implements VideoTech { } if (callback == null) { - callback = new ImsVideoCallCallback(call, this, listener); + callback = new ImsVideoCallCallback(logger, call, this, listener); call.getVideoCall().registerCallback(callback); } @@ -137,6 +142,7 @@ public class ImsVideoTech implements VideoTech { .sendSessionModifyRequest( new VideoProfile(unpausedVideoState | VideoProfile.STATE_BIDIRECTIONAL)); setSessionModificationState(SessionModificationState.WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE); + logger.logImpression(DialerImpression.Type.IMS_VIDEO_UPGRADE_REQUESTED); } @Override @@ -146,6 +152,9 @@ public class ImsVideoTech implements VideoTech { LogUtil.i("ImsVideoTech.acceptUpgradeRequest", "videoState: " + requestedVideoState); call.getVideoCall().sendSessionModifyResponse(new VideoProfile(requestedVideoState)); setSessionModificationState(SessionModificationState.NO_REQUEST); + // Telecom manages audio route for us + listener.onUpgradedToVideo(false /* switchToSpeaker */); + logger.logImpression(DialerImpression.Type.IMS_VIDEO_REQUEST_ACCEPTED); } @Override @@ -153,6 +162,7 @@ public class ImsVideoTech implements VideoTech { LogUtil.enterBlock("ImsVideoTech.acceptVideoRequestAsAudio"); call.getVideoCall().sendSessionModifyResponse(new VideoProfile(VideoProfile.STATE_AUDIO_ONLY)); setSessionModificationState(SessionModificationState.NO_REQUEST); + logger.logImpression(DialerImpression.Type.IMS_VIDEO_REQUEST_ACCEPTED_AS_AUDIO); } @Override @@ -161,6 +171,7 @@ public class ImsVideoTech implements VideoTech { call.getVideoCall() .sendSessionModifyResponse(new VideoProfile(call.getDetails().getVideoState())); setSessionModificationState(SessionModificationState.NO_REQUEST); + logger.logImpression(DialerImpression.Type.IMS_VIDEO_REQUEST_DECLINED); } @Override @@ -191,23 +202,33 @@ public class ImsVideoTech implements VideoTech { @Override public void pause() { - if (canPause()) { + if (canPause() && !paused) { LogUtil.i("ImsVideoTech.pause", "sending pause request"); + paused = true; int pausedVideoState = call.getDetails().getVideoState() | VideoProfile.STATE_PAUSED; call.getVideoCall().sendSessionModifyRequest(new VideoProfile(pausedVideoState)); } else { - LogUtil.i("ImsVideoTech.pause", "not sending request: canPause: %b", canPause()); + LogUtil.i( + "ImsVideoTech.pause", + "not sending request: canPause: %b, paused: %b", + canPause(), + paused); } } @Override public void unpause() { - if (canPause()) { + if (canPause() && paused) { LogUtil.i("ImsVideoTech.unpause", "sending unpause request"); + paused = false; int unpausedVideoState = getUnpausedVideoState(call.getDetails().getVideoState()); call.getVideoCall().sendSessionModifyRequest(new VideoProfile(unpausedVideoState)); } else { - LogUtil.i("ImsVideoTech.unpause", "not sending request: canPause: %b", canPause()); + LogUtil.i( + "ImsVideoTech.unpause", + "not sending request: canPause: %b, paused: %b", + canPause(), + paused); } } @@ -224,7 +245,8 @@ public class ImsVideoTech implements VideoTech { private boolean canPause() { return call.getDetails().can(Details.CAPABILITY_CAN_PAUSE_VIDEO) - && call.getState() == Call.STATE_ACTIVE; + && call.getState() == Call.STATE_ACTIVE + && isTransmitting(); } static int getUnpausedVideoState(int videoState) { diff --git a/java/com/android/incallui/wifi/res/values-b+sr+Latn/strings.xml b/java/com/android/incallui/wifi/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..51a57e403197160c7e576f77c7a2281365b333de --- /dev/null +++ b/java/com/android/incallui/wifi/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,5 @@ + + + "Omogući" + diff --git a/java/com/android/voicemail/VoicemailClient.java b/java/com/android/voicemail/VoicemailClient.java index 74823384c8c0dc40b785e690ac6caf0697aeb403..97b824b274facf8f52e6e0c604bc3baa7f7255d6 100644 --- a/java/com/android/voicemail/VoicemailClient.java +++ b/java/com/android/voicemail/VoicemailClient.java @@ -39,11 +39,33 @@ public interface VoicemailClient { * android.content.Intent#ACTION_PROVIDER_CHANGED} will always be a self-change even if the UI is * external to the client. */ - String ACTION_UPLOAD = "com.android.voicemailomtp.VoicemailClient.ACTION_UPLOAD"; + String ACTION_UPLOAD = "com.android.voicemail.VoicemailClient.ACTION_UPLOAD"; /** Common key for passing {@link PhoneAccountHandle} in bundles. */ String PARAM_PHONE_ACCOUNT_HANDLE = "phone_account_handle"; + /** + * Broadcast from the client to inform the app to show a legacy voicemail notification. This + * broadcast is same as {@link TelephonyManager#ACTION_SHOW_VOICEMAIL_NOTIFICATION}. + */ + String ACTION_SHOW_LEGACY_VOICEMAIL = + "com.android.voicemail.VoicemailClient.ACTION_SHOW_LEGACY_VOICEMAIL"; + + /** + * Whether the visual voicemail service is enabled for the {@code phoneAccountHandle}. "Enable" + * means the user "wants" to have this service on, and does not mean the service is actually + * functional(For example, the service is blocked on the carrier side. The service will be + * "enabled" but all it will do is show the error). + */ + boolean isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle); + + /** + * Enable or disable visual voicemail service for the {@code phoneAccountHandle}. Setting to + * enabled will initiate provisioning and activation. Setting to disabled will initiate + * deactivation. + */ + void setVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled); + /** * Appends the selection to ignore voicemails from non-active OMTP voicemail package. In OC there * can be multiple packages handling OMTP voicemails which represents the same source of truth. @@ -92,4 +114,12 @@ public interface VoicemailClient { * when calling into the mailbox. */ Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle); + + /** + * Whether the client is activated and handling visual voicemail for the {@code + * phoneAccountHandle}. "Enable" is the intention to use VVM. For example VVM can be enabled but + * prevented from working because the carrier blocked it, or a connection problem is blocking the + * provisioning. Being "activated" means all setup are completed, and VVM is expected to work. + */ + boolean isActivated(Context context, PhoneAccountHandle phoneAccountHandle); } diff --git a/java/com/android/voicemail/VoicemailPermissionHelper.java b/java/com/android/voicemail/VoicemailPermissionHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..1a09d45fdaca0c2834693da2ae294a7833ec127a --- /dev/null +++ b/java/com/android/voicemail/VoicemailPermissionHelper.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 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.voicemail; + +import android.Manifest.permission; +import android.content.Context; +import android.content.pm.PackageManager; +import android.support.annotation.NonNull; +import java.util.ArrayList; +import java.util.List; + +/** + * Handles permission checking for the voicemail module. Currently "phone" and "sms" permissions are + * required. + */ +public class VoicemailPermissionHelper { + + /** *_VOICEMAIL permissions are auto-granted by being the default dialer. */ + private static final String[] VOICEMAIL_PERMISSIONS = { + permission.ADD_VOICEMAIL, + permission.WRITE_VOICEMAIL, + permission.READ_VOICEMAIL, + permission.READ_PHONE_STATE, + permission.SEND_SMS + }; + + /** + * Returns {@code true} if the app has all permissions required for the voicemail module to + * operate. + */ + public static boolean hasPermissions(Context context) { + return getMissingPermissions(context).isEmpty(); + } + + /** Returns a list of permission that is missing for the voicemail module to operate. */ + @NonNull + public static List getMissingPermissions(Context context) { + List result = new ArrayList<>(); + for (String permission : VOICEMAIL_PERMISSIONS) { + if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { + result.add(permission); + } + } + return result; + } +} diff --git a/java/com/android/voicemail/impl/ActivationTask.java b/java/com/android/voicemail/impl/ActivationTask.java index c53d3c722389e1098fd9bbad25a3455be9190ee8..6e27b501523cf6313f1b66c1749ef61328076beb 100644 --- a/java/com/android/voicemail/impl/ActivationTask.java +++ b/java/com/android/voicemail/impl/ActivationTask.java @@ -19,18 +19,17 @@ package com.android.voicemail.impl; import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; -import android.database.ContentObserver; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.provider.Settings; -import android.provider.Settings.Global; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; import android.telecom.PhoneAccountHandle; import android.telephony.ServiceState; import android.telephony.TelephonyManager; -import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.proguard.UsedByReflection; +import com.android.voicemail.VoicemailClient; import com.android.voicemail.impl.protocol.VisualVoicemailProtocol; import com.android.voicemail.impl.scheduling.BaseTask; import com.android.voicemail.impl.scheduling.RetryPolicy; @@ -40,9 +39,8 @@ import com.android.voicemail.impl.sms.StatusSmsFetcher; import com.android.voicemail.impl.sync.OmtpVvmSyncService; import com.android.voicemail.impl.sync.SyncTask; import com.android.voicemail.impl.sync.VvmAccountManager; +import com.android.voicemail.impl.utils.LoggerUtils; import java.io.IOException; -import java.util.HashSet; -import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -55,6 +53,7 @@ import java.util.concurrent.TimeoutException; * spontaneously sent a STATUS SMS. */ @TargetApi(VERSION_CODES.O) +@UsedByReflection(value = "Tasks.java") public class ActivationTask extends BaseTask { private static final String TAG = "VvmActivationTask"; @@ -64,8 +63,6 @@ public class ActivationTask extends BaseTask { private static final String EXTRA_MESSAGE_DATA_BUNDLE = "extra_message_data_bundle"; - @Nullable private static DeviceProvisionedObserver sDeviceProvisionedObserver; - private final RetryPolicy mRetryPolicy; private Bundle mMessageData; @@ -95,7 +92,7 @@ public class ActivationTask extends BaseTask { // Activation might need information such as system language to be set, so wait until // the setup wizard is finished. The data bundle from the SMS will be re-requested upon // activation. - queueActivationAfterProvisioned(context, phoneAccountHandle); + DeviceProvisionedJobService.activateAfterProvisioned(context, phoneAccountHandle); return; } @@ -103,18 +100,19 @@ public class ActivationTask extends BaseTask { if (messageData != null) { intent.putExtra(EXTRA_MESSAGE_DATA_BUNDLE, messageData); } - context.startService(intent); + context.sendBroadcast(intent); } @Override - public void onCreate(Context context, Intent intent, int flags, int startId) { - super.onCreate(context, intent, flags, startId); - mMessageData = intent.getParcelableExtra(EXTRA_MESSAGE_DATA_BUNDLE); + public void onCreate(Context context, Bundle extras) { + super.onCreate(context, extras); + mMessageData = extras.getParcelable(EXTRA_MESSAGE_DATA_BUNDLE); } @Override public Intent createRestartIntent() { - Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_AUTO_RETRY_ACTIVATION); + LoggerUtils.logImpressionOnMainThread( + getContext(), DialerImpression.Type.VVM_AUTO_RETRY_ACTIVATION); Intent intent = super.createRestartIntent(); // mMessageData is discarded, request a fresh STATUS SMS for retries. return intent; @@ -124,7 +122,8 @@ public class ActivationTask extends BaseTask { @WorkerThread public void onExecuteInBackgroundThread() { Assert.isNotMainThread(); - Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_ACTIVATION_STARTED); + LoggerUtils.logImpressionOnMainThread( + getContext(), DialerImpression.Type.VVM_ACTIVATION_STARTED); PhoneAccountHandle phoneAccountHandle = getPhoneAccountHandle(); if (phoneAccountHandle == null) { // This should never happen @@ -132,6 +131,8 @@ public class ActivationTask extends BaseTask { return; } + PreOMigrationHandler.migrate(getContext(), phoneAccountHandle); + if (!VisualVoicemailSettingsUtil.isEnabled(getContext(), phoneAccountHandle)) { VvmLog.i(TAG, "VVM is disabled"); return; @@ -159,6 +160,7 @@ public class ActivationTask extends BaseTask { if (VvmAccountManager.isAccountActivated(getContext(), phoneAccountHandle)) { VvmLog.i(TAG, "Account is already activated"); + onSuccess(getContext(), phoneAccountHandle); return; } helper.handleEvent( @@ -218,7 +220,7 @@ public class ActivationTask extends BaseTask { + message.getReturnCode()); if (message.getProvisioningStatus().equals(OmtpConstants.SUBSCRIBER_READY)) { VvmLog.d(TAG, "subscriber ready, no activation required"); - updateSource(getContext(), phoneAccountHandle, status, message); + updateSource(getContext(), phoneAccountHandle, message); } else { if (helper.supportsProvisioning()) { VvmLog.i(TAG, "Subscriber not ready, start provisioning"); @@ -228,34 +230,48 @@ public class ActivationTask extends BaseTask { VvmLog.i(TAG, "Subscriber new but provisioning is not supported"); // Ignore the non-ready state and attempt to use the provided info as is. // This is probably caused by not completing the new user tutorial. - updateSource(getContext(), phoneAccountHandle, status, message); + updateSource(getContext(), phoneAccountHandle, message); } else { VvmLog.i(TAG, "Subscriber not ready but provisioning is not supported"); helper.handleEvent(status, OmtpEvents.CONFIG_SERVICE_NOT_AVAILABLE); } } - Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_ACTIVATION_COMPLETED); + LoggerUtils.logImpressionOnMainThread( + getContext(), DialerImpression.Type.VVM_ACTIVATION_COMPLETED); } - public static void updateSource( - Context context, - PhoneAccountHandle phone, - VoicemailStatus.Editor status, - StatusMessage message) { + private static void updateSource( + Context context, PhoneAccountHandle phone, StatusMessage message) { if (OmtpConstants.SUCCESS.equals(message.getReturnCode())) { - OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, phone); - helper.handleEvent(status, OmtpEvents.CONFIG_REQUEST_STATUS_SUCCESS); - // Save the IMAP credentials in preferences so they are persistent and can be retrieved. VvmAccountManager.addAccount(context, phone, message); - - SyncTask.start(context, phone, OmtpVvmSyncService.SYNC_FULL_SYNC); + onSuccess(context, phone); } else { VvmLog.e(TAG, "Visual voicemail not available for subscriber."); } } + private static void onSuccess(Context context, PhoneAccountHandle phoneAccountHandle) { + OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle); + helper.handleEvent( + VoicemailStatus.edit(context, phoneAccountHandle), + OmtpEvents.CONFIG_REQUEST_STATUS_SUCCESS); + clearLegacyVoicemailNotification(context, phoneAccountHandle); + SyncTask.start(context, phoneAccountHandle, OmtpVvmSyncService.SYNC_FULL_SYNC); + } + + /** Sends a broadcast to the dialer UI to clear legacy voicemail notifications if any. */ + private static void clearLegacyVoicemailNotification( + Context context, PhoneAccountHandle phoneAccountHandle) { + Intent intent = new Intent(VoicemailClient.ACTION_SHOW_LEGACY_VOICEMAIL); + intent.setPackage(context.getPackageName()); + intent.putExtra(TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); + // Setting voicemail message count to zero will clear the notification. + intent.putExtra(TelephonyManager.EXTRA_NOTIFICATION_COUNT, 0); + context.sendBroadcast(intent); + } + private static boolean hasSignal(Context context, PhoneAccountHandle phoneAccountHandle) { TelephonyManager telephonyManager = context @@ -263,45 +279,4 @@ public class ActivationTask extends BaseTask { .createForPhoneAccountHandle(phoneAccountHandle); return telephonyManager.getServiceState().getState() == ServiceState.STATE_IN_SERVICE; } - - private static void queueActivationAfterProvisioned( - Context context, PhoneAccountHandle phoneAccountHandle) { - if (sDeviceProvisionedObserver == null) { - sDeviceProvisionedObserver = new DeviceProvisionedObserver(context); - context - .getContentResolver() - .registerContentObserver( - Settings.Global.getUriFor(Global.DEVICE_PROVISIONED), - false, - sDeviceProvisionedObserver); - } - sDeviceProvisionedObserver.addPhoneAcountHandle(phoneAccountHandle); - } - - private static class DeviceProvisionedObserver extends ContentObserver { - - private final Context mContext; - private final Set mPhoneAccountHandles = new HashSet<>(); - - private DeviceProvisionedObserver(Context context) { - super(null); - mContext = context; - } - - public void addPhoneAcountHandle(PhoneAccountHandle phoneAccountHandle) { - mPhoneAccountHandles.add(phoneAccountHandle); - } - - @Override - public void onChange(boolean selfChange) { - if (isDeviceProvisioned(mContext)) { - VvmLog.i(TAG, "device provisioned, resuming activation"); - for (PhoneAccountHandle phoneAccountHandle : mPhoneAccountHandles) { - start(mContext, phoneAccountHandle, null); - } - mContext.getContentResolver().unregisterContentObserver(sDeviceProvisionedObserver); - sDeviceProvisionedObserver = null; - } - } - } } diff --git a/java/com/android/voicemail/impl/AndroidManifest.xml b/java/com/android/voicemail/impl/AndroidManifest.xml index 97e397385470417164ad9035b53d64d315d616d8..3e512ba1ed0f8eb3cacf835e86efa4705efd54ad 100644 --- a/java/com/android/voicemail/impl/AndroidManifest.xml +++ b/java/com/android/voicemail/impl/AndroidManifest.xml @@ -31,7 +31,8 @@ + android:exported="false" + android:directBootAware="true"> @@ -40,7 +41,7 @@ - + @@ -76,21 +77,46 @@ - - + + + + + + + - + - + + + + + + + diff --git a/java/com/android/voicemail/impl/DeviceProvisionedJobService.java b/java/com/android/voicemail/impl/DeviceProvisionedJobService.java new file mode 100644 index 0000000000000000000000000000000000000000..a0b999d23f409933ef004e49e6292e078216355f --- /dev/null +++ b/java/com/android/voicemail/impl/DeviceProvisionedJobService.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2017 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.voicemail.impl; + +import android.annotation.TargetApi; +import android.app.job.JobInfo; +import android.app.job.JobInfo.TriggerContentUri; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.app.job.JobWorkItem; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Build.VERSION_CODES; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.telecom.PhoneAccountHandle; +import com.android.dialer.constants.ScheduledJobIds; + +/** + * JobService triggered when the setup wizard is completed, and rerun all {@link ActivationTask} + * scheduled during the setup. + */ +@TargetApi(VERSION_CODES.O) +public class DeviceProvisionedJobService extends JobService { + + private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "EXTRA_PHONE_ACCOUNT_HANDLE"; + + /** Queue the phone account to be reactivated after the setup wizard has completed. */ + public static void activateAfterProvisioned( + Context context, PhoneAccountHandle phoneAccountHandle) { + JobInfo jobInfo = + new JobInfo.Builder( + ScheduledJobIds.VVM_DEVICE_PROVISIONED_JOB, + new ComponentName(context, DeviceProvisionedJobService.class)) + .addTriggerContentUri( + new TriggerContentUri(Global.getUriFor(Global.DEVICE_PROVISIONED), 0)) + // VVM activation must be run as soon as possible to avoid voicemail loss + .setTriggerContentMaxDelay(0) + .build(); + + Intent intent = new Intent(); + intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); + context.getSystemService(JobScheduler.class).enqueue(jobInfo, new JobWorkItem(intent)); + } + + @Override + public boolean onStartJob(JobParameters params) { + Assert.isTrue(isDeviceProvisioned()); + VvmLog.i("DeviceProvisionedJobService.onStartJob", "device provisioned"); + for (JobWorkItem item = params.dequeueWork(); item != null; item = params.dequeueWork()) { + PhoneAccountHandle phoneAccountHandle = + item.getIntent().getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE); + VvmLog.i( + "DeviceProvisionedJobService.onStartJob", + "restarting activation for " + phoneAccountHandle); + ActivationTask.start(this, phoneAccountHandle, null); + } + return false; // job not running in background + } + + @Override + public boolean onStopJob(JobParameters params) { + return true; // reschedule job + } + + private boolean isDeviceProvisioned() { + return Settings.Global.getInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) == 1; + } +} diff --git a/java/com/android/voicemail/impl/OmtpReceiver.java b/java/com/android/voicemail/impl/OmtpReceiver.java index 239a544c49bfbb3903acc7665d0558ca3cd7e1ac..9baf9541598d4838ff719c0358c7e18f8a5d5c39 100644 --- a/java/com/android/voicemail/impl/OmtpReceiver.java +++ b/java/com/android/voicemail/impl/OmtpReceiver.java @@ -24,8 +24,8 @@ import android.os.Build.VERSION_CODES; import android.telecom.PhoneAccountHandle; import android.telephony.VisualVoicemailSms; import com.android.dialer.common.Assert; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; import com.android.voicemail.impl.sync.VvmAccountManager; diff --git a/java/com/android/voicemail/impl/OmtpService.java b/java/com/android/voicemail/impl/OmtpService.java new file mode 100644 index 0000000000000000000000000000000000000000..759be4fd1285368c9a58450ce6a4b687a5971f63 --- /dev/null +++ b/java/com/android/voicemail/impl/OmtpService.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2017 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.voicemail.impl; + +import android.annotation.TargetApi; +import android.content.Intent; +import android.os.Build.VERSION_CODES; +import android.os.UserManager; +import android.telecom.PhoneAccountHandle; +import android.telephony.VisualVoicemailService; +import android.telephony.VisualVoicemailSms; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.voicemail.VoicemailComponent; +import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; +import com.android.voicemail.impl.sms.LegacyModeSmsHandler; +import com.android.voicemail.impl.sync.VvmAccountManager; + +/** Implements {@link VisualVoicemailService} to receive visual voicemail events */ +@TargetApi(VERSION_CODES.O) +public class OmtpService extends VisualVoicemailService { + + private static final String TAG = "VvmOmtpService"; + + public static final String ACTION_SMS_RECEIVED = "com.android.vociemailomtp.sms.sms_received"; + + public static final String EXTRA_VOICEMAIL_SMS = "extra_voicemail_sms"; + + @Override + public void onCellServiceConnected( + VisualVoicemailTask task, final PhoneAccountHandle phoneAccountHandle) { + VvmLog.i(TAG, "onCellServiceConnected"); + if (!isModuleEnabled()) { + VvmLog.e(TAG, "onCellServiceConnected received when module is disabled"); + task.finish(); + return; + } + + if (!isUserUnlocked()) { + VvmLog.i(TAG, "onCellServiceConnected: user locked"); + task.finish(); + return; + } + + if (!isServiceEnabled(phoneAccountHandle)) { + task.finish(); + return; + } + + Logger.get(this).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); + ActivationTask.start(OmtpService.this, phoneAccountHandle, null); + task.finish(); + } + + @Override + public void onSmsReceived(VisualVoicemailTask task, final VisualVoicemailSms sms) { + VvmLog.i(TAG, "onSmsReceived"); + if (!isModuleEnabled()) { + VvmLog.e(TAG, "onSmsReceived received when module is disabled"); + task.finish(); + return; + } + + if (!isUserUnlocked()) { + LegacyModeSmsHandler.handle(this, sms); + return; + } + + VvmPackageInstallHandler.scanNewPackages(this); + + if (!isServiceEnabled(sms.getPhoneAccountHandle())) { + task.finish(); + return; + } + + // isUserUnlocked() is not checked. OmtpMessageReceiver will handle the locked case. + + Logger.get(this).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); + Intent intent = new Intent(ACTION_SMS_RECEIVED); + intent.setPackage(getPackageName()); + intent.putExtra(EXTRA_VOICEMAIL_SMS, sms); + sendBroadcast(intent); + task.finish(); + } + + @Override + public void onSimRemoved( + final VisualVoicemailTask task, final PhoneAccountHandle phoneAccountHandle) { + VvmLog.i(TAG, "onSimRemoved"); + if (!isModuleEnabled()) { + VvmLog.e(TAG, "onSimRemoved called when module is disabled"); + task.finish(); + return; + } + + if (!isUserUnlocked()) { + VvmLog.i(TAG, "onSimRemoved: user locked"); + task.finish(); + return; + } + + Logger.get(this).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); + VvmAccountManager.removeAccount(this, phoneAccountHandle); + task.finish(); + } + + @Override + public void onStopped(VisualVoicemailTask task) { + VvmLog.i(TAG, "onStopped"); + if (!isModuleEnabled()) { + VvmLog.e(TAG, "onStopped called when module is disabled"); + task.finish(); + return; + } + if (!isUserUnlocked()) { + VvmLog.i(TAG, "onStopped: user locked"); + task.finish(); + return; + } + Logger.get(this).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); + } + + private boolean isModuleEnabled() { + return VoicemailComponent.get(this).getVoicemailClient().isVoicemailModuleEnabled(); + } + + private boolean isServiceEnabled(PhoneAccountHandle phoneAccountHandle) { + OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(this, phoneAccountHandle); + if (!config.isValid()) { + VvmLog.i(TAG, "VVM not supported on " + phoneAccountHandle); + return false; + } + if (!VisualVoicemailSettingsUtil.isEnabled(this, phoneAccountHandle) + && !config.isLegacyModeEnabled()) { + VvmLog.i(TAG, "VVM is disabled"); + return false; + } + return true; + } + + private boolean isUserUnlocked() { + UserManager userManager = getSystemService(UserManager.class); + return userManager.isUserUnlocked(); + } +} diff --git a/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java b/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java index 095f00bb7f0f1537894c4ff86803e24100a6f49e..4a9e4337071aa08eaa4f26ff9000832d93d1064b 100644 --- a/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java +++ b/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java @@ -26,7 +26,6 @@ import android.support.annotation.VisibleForTesting; import android.telecom.PhoneAccountHandle; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; -import android.telephony.VisualVoicemailService; import android.telephony.VisualVoicemailSmsFilterSettings; import android.text.TextUtils; import android.util.ArraySet; @@ -108,8 +107,7 @@ public class OmtpVvmCarrierConfigHelper { mCarrierConfig = getCarrierConfig(telephonyManager); mTelephonyConfig = - new TelephonyVvmConfigManager(context.getResources()) - .getConfig(telephonyManager.getSimOperator()); + new TelephonyVvmConfigManager(context).getConfig(telephonyManager.getSimOperator()); mVvmType = getVvmType(); mProtocol = VisualVoicemailProtocolFactory.create(mContext.getResources(), mVvmType); @@ -234,9 +232,7 @@ public class OmtpVvmCarrierConfigHelper { return (String) getValue(KEY_VVM_DESTINATION_NUMBER_STRING); } - /** - * @return Port to start a SSL IMAP connection directly. - */ + /** @return Port to start a SSL IMAP connection directly. */ public int getSslPort() { Assert.checkArgument(isValid()); return (int) getValue(KEY_VVM_SSL_PORT_NUMBER_INT, 0); @@ -328,7 +324,7 @@ public class OmtpVvmCarrierConfigHelper { public void activateSmsFilter() { Assert.checkArgument(isValid()); - VisualVoicemailService.setSmsFilterSettings( + TelephonyMangerCompat.setVisualVoicemailSmsFilterSettings( mContext, getPhoneAccountHandle(), new VisualVoicemailSmsFilterSettings.Builder().setClientPrefix(getClientPrefix()).build()); @@ -336,9 +332,12 @@ public class OmtpVvmCarrierConfigHelper { public void startDeactivation() { Assert.checkArgument(isValid()); + VvmLog.i(TAG, "startDeactivation"); if (!isLegacyModeEnabled()) { // SMS should still be filtered in legacy mode - VisualVoicemailService.setSmsFilterSettings(mContext, getPhoneAccountHandle(), null); + TelephonyMangerCompat.setVisualVoicemailSmsFilterSettings( + mContext, getPhoneAccountHandle(), null); + VvmLog.i(TAG, "filter disabled"); } if (mProtocol != null) { mProtocol.startDeactivation(this); diff --git a/java/com/android/voicemail/impl/PreOMigrationHandler.java b/java/com/android/voicemail/impl/PreOMigrationHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..6dc2dee90e4752b78438838595dc4a755a2c1600 --- /dev/null +++ b/java/com/android/voicemail/impl/PreOMigrationHandler.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 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.voicemail.impl; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.WorkerThread; +import android.telecom.PhoneAccountHandle; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; +import com.android.voicemail.impl.settings.VoicemailChangePinActivity; +import java.lang.reflect.Method; + +/** Handles migration of data from the visual voicemail client in telephony before O. */ +public final class PreOMigrationHandler { + + // Hidden system APIs to access pre O VVM data + // Bundle getVisualVoicemailSettings() + private static final String METHOD_GET_VISUAL_VOICEMAIL_SETTINGS = "getVisualVoicemailSettings"; + + /** + * Key in bundle returned by {@link #METHOD_GET_VISUAL_VOICEMAIL_SETTINGS}, indicating whether + * visual voicemail was enabled or disabled by the user. If the user never explicitly changed this + * setting, this key will not exist. + */ + private static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = + "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; + + /** + * Key in bundle returned by {@link #METHOD_GET_VISUAL_VOICEMAIL_SETTINGS}, indicating the + * voicemail access PIN scrambled during the auto provisioning process. The user is expected to + * reset their PIN if this value is not {@code null}. + */ + private static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = + "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; + + private static final String PRE_O_MIGRATION_FINISHED = "pre_o_migration_finished"; + + @WorkerThread + public static void migrate(Context context, PhoneAccountHandle phoneAccountHandle) { + Assert.isNotMainThread(); + VisualVoicemailPreferences preferences = + new VisualVoicemailPreferences(context, phoneAccountHandle); + if (preferences.getBoolean(PRE_O_MIGRATION_FINISHED, false)) { + VvmLog.i("PreOMigrationHandler", phoneAccountHandle + " already migrated"); + return; + } + VvmLog.i("PreOMigrationHandler", "migrating " + phoneAccountHandle); + migrateSettings(context, phoneAccountHandle); + + preferences.edit().putBoolean(PRE_O_MIGRATION_FINISHED, true).apply(); + } + + private static void migrateSettings(Context context, PhoneAccountHandle phoneAccountHandle) { + VvmLog.i("PreOMigrationHandler.migrateSettings", "migrating settings"); + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(phoneAccountHandle); + if (telephonyManager == null) { + VvmLog.e("PreOMigrationHandler.migrateSettings", "invalid PhoneAccountHandle"); + return; + } + Bundle legacySettings; + try { + Method method = TelephonyManager.class.getMethod(METHOD_GET_VISUAL_VOICEMAIL_SETTINGS); + legacySettings = (Bundle) method.invoke(telephonyManager); + } catch (ReflectiveOperationException | ClassCastException e) { + VvmLog.i("PreOMigrationHandler.migrateSettings", "unable to retrieve settings from system"); + return; + } + + if (legacySettings.containsKey(EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL)) { + boolean enabled = legacySettings.getBoolean(EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL); + VvmLog.i("PreOMigrationHandler.migrateSettings", "setting VVM enabled to " + enabled); + VisualVoicemailSettingsUtil.setEnabled(context, phoneAccountHandle, enabled); + } + + if (legacySettings.containsKey(EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING)) { + String scrambledPin = legacySettings.getString(EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING); + if (!TextUtils.isEmpty(scrambledPin)) { + VvmLog.i("PreOMigrationHandler.migrateSettings", "migrating scrambled PIN"); + VoicemailChangePinActivity.setDefaultOldPIN(context, phoneAccountHandle, scrambledPin); + } + } + } +} diff --git a/java/com/android/voicemail/impl/StatusCheckJobService.java b/java/com/android/voicemail/impl/StatusCheckJobService.java new file mode 100644 index 0000000000000000000000000000000000000000..870c5b47190876173395b80303255830f97cbca9 --- /dev/null +++ b/java/com/android/voicemail/impl/StatusCheckJobService.java @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2017 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.voicemail.impl; + +import android.annotation.TargetApi; +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.os.Build.VERSION_CODES; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import com.android.dialer.constants.ScheduledJobIds; +import com.android.voicemail.impl.sync.VvmAccountManager; +import java.util.concurrent.TimeUnit; + +/** + * A job to perform {@link StatusCheckTask} once per day, performing book keeping to ensure the + * credentials and status for a activated voicemail account is still correct. A task will be + * scheduled for each active voicemail account. The status is expected to be always in sync, the + * check is a failsafe to mimic the previous status check on signal return behavior. + */ +@TargetApi(VERSION_CODES.O) +public class StatusCheckJobService extends JobService { + + public static void schedule(Context context) { + JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); + if (jobScheduler.getPendingJob(ScheduledJobIds.VVM_STATUS_CHECK_JOB) != null) { + VvmLog.i("StatusCheckJobService.schedule", "job already scheduled"); + return; + } + + jobScheduler.schedule( + new JobInfo.Builder( + ScheduledJobIds.VVM_STATUS_CHECK_JOB, + new ComponentName(context, StatusCheckJobService.class)) + .setPeriodic(TimeUnit.DAYS.toMillis(1)) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) + .setRequiresCharging(true) + .build()); + } + + @Override + public boolean onStartJob(JobParameters params) { + for (PhoneAccountHandle phoneAccountHandle : + getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) { + if (VvmAccountManager.isAccountActivated(this, phoneAccountHandle)) { + StatusCheckTask.start(this, phoneAccountHandle); + } + } + return false; // not running in background + } + + @Override + public boolean onStopJob(JobParameters params) { + return false; // don't retry + } +} diff --git a/java/com/android/voicemail/impl/StatusCheckTask.java b/java/com/android/voicemail/impl/StatusCheckTask.java new file mode 100644 index 0000000000000000000000000000000000000000..e59eb3b37ee038aa148975aa177f166f69c6bb44 --- /dev/null +++ b/java/com/android/voicemail/impl/StatusCheckTask.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2017 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.voicemail.impl; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import android.telecom.PhoneAccountHandle; +import android.telephony.ServiceState; +import android.telephony.TelephonyManager; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.proguard.UsedByReflection; +import com.android.voicemail.impl.scheduling.BaseTask; +import com.android.voicemail.impl.sms.StatusMessage; +import com.android.voicemail.impl.sms.StatusSmsFetcher; +import com.android.voicemail.impl.sync.VvmAccountManager; +import com.android.voicemail.impl.utils.LoggerUtils; +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * Task to verify the account status is still correct. This task is only for book keeping so any + * error is ignored and will not retry. If the provision status sent by the carrier is "ready" the + * access credentials will be updated (although it is not expected to change without the carrier + * actively sending out an STATUS SMS which will be handled by {@link + * com.android.voicemail.impl.sms.OmtpMessageReceiver}). If the provisioning status is not ready an + * {@link ActivationTask} will be launched to attempt to correct it. + */ +@TargetApi(VERSION_CODES.O) +@UsedByReflection(value = "Tasks.java") +public class StatusCheckTask extends BaseTask { + + public StatusCheckTask() { + super(TASK_STATUS_CHECK); + } + + public static void start(Context context, PhoneAccountHandle phoneAccountHandle) { + Intent intent = BaseTask.createIntent(context, StatusCheckTask.class, phoneAccountHandle); + context.sendBroadcast(intent); + } + + @Override + public void onExecuteInBackgroundThread() { + TelephonyManager telephonyManager = + getContext() + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(getPhoneAccountHandle()); + + if (telephonyManager == null) { + VvmLog.w( + "StatusCheckTask.onExecuteInBackgroundThread", + getPhoneAccountHandle() + " no longer valid"); + return; + } + if (telephonyManager.getServiceState().getState() != ServiceState.STATE_IN_SERVICE) { + VvmLog.i( + "StatusCheckTask.onExecuteInBackgroundThread", + getPhoneAccountHandle() + " not in service"); + return; + } + OmtpVvmCarrierConfigHelper config = + new OmtpVvmCarrierConfigHelper(getContext(), getPhoneAccountHandle()); + if (!config.isValid()) { + VvmLog.e( + "StatusCheckTask.onExecuteInBackgroundThread", + "config no longer valid for " + getPhoneAccountHandle()); + VvmAccountManager.removeAccount(getContext(), getPhoneAccountHandle()); + return; + } + + Bundle data; + try (StatusSmsFetcher fetcher = new StatusSmsFetcher(getContext(), getPhoneAccountHandle())) { + config.getProtocol().requestStatus(config, fetcher.getSentIntent()); + // Both the fetcher and OmtpMessageReceiver will be triggered, but + // OmtpMessageReceiver will just route the SMS back to ActivationTask, which will be + // rejected because the task is still running. + data = fetcher.get(); + } catch (TimeoutException e) { + VvmLog.e("StatusCheckTask.onExecuteInBackgroundThread", "timeout requesting status"); + return; + } catch (CancellationException e) { + VvmLog.e("StatusCheckTask.onExecuteInBackgroundThread", "Unable to send status request SMS"); + return; + } catch (InterruptedException | ExecutionException | IOException e) { + VvmLog.e("StatusCheckTask.onExecuteInBackgroundThread", "can't get future STATUS SMS", e); + return; + } + + StatusMessage message = new StatusMessage(data); + VvmLog.i( + "StatusCheckTask.onExecuteInBackgroundThread", + "STATUS SMS received: st=" + + message.getProvisioningStatus() + + ", rc=" + + message.getReturnCode()); + if (message.getProvisioningStatus().equals(OmtpConstants.SUBSCRIBER_READY)) { + VvmLog.i( + "StatusCheckTask.onExecuteInBackgroundThread", + "subscriber ready, no activation required"); + LoggerUtils.logImpressionOnMainThread( + getContext(), DialerImpression.Type.VVM_STATUS_CHECK_READY); + VvmAccountManager.addAccount(getContext(), getPhoneAccountHandle(), message); + } else { + VvmLog.i( + "StatusCheckTask.onExecuteInBackgroundThread", + "subscriber not ready, attempting reactivation"); + VvmAccountManager.removeAccount(getContext(), getPhoneAccountHandle()); + LoggerUtils.logImpressionOnMainThread( + getContext(), DialerImpression.Type.VVM_STATUS_CHECK_REACTIVATION); + ActivationTask.start(getContext(), getPhoneAccountHandle(), data); + } + } +} diff --git a/java/com/android/voicemail/impl/TelephonyMangerCompat.java b/java/com/android/voicemail/impl/TelephonyMangerCompat.java index 353cd69e3fe2e89a8c9606948fc84ed2c8d580c5..404b4d6cabc1d417f989192559ea8355a59c4f20 100644 --- a/java/com/android/voicemail/impl/TelephonyMangerCompat.java +++ b/java/com/android/voicemail/impl/TelephonyMangerCompat.java @@ -16,24 +16,36 @@ package com.android.voicemail.impl; +import android.app.PendingIntent; +import android.content.Context; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; +import android.telephony.VisualVoicemailService; +import android.telephony.VisualVoicemailSmsFilterSettings; +import com.android.dialer.common.LogUtil; import java.lang.reflect.Method; /** Handles {@link TelephonyManager} API changes in experimental SDK */ public class TelephonyMangerCompat { - - private static final String GET_VISUAL_VOICEMAIL_PACKGE_NAME = "getVisualVoicemailPackageName"; - - /** - * Changed from getVisualVoicemailPackageName(PhoneAccountHandle) to - * getVisualVoicemailPackageName() - */ - public static String getVisualVoicemailPackageName(TelephonyManager telephonyManager) { + /** Moved from VisualVoicemailService to TelephonyManager */ + public static String sendVisualVoicemailSms( + Context context, + PhoneAccountHandle phoneAccountHandle, + String number, + int port, + String text, + PendingIntent sentIntent) { try { - Method method = TelephonyManager.class.getMethod(GET_VISUAL_VOICEMAIL_PACKGE_NAME); + Method method = + TelephonyManager.class.getMethod( + "sendVisualVoicemailSms", String.class, int.class, String.class, PendingIntent.class); try { - return (String) method.invoke(telephonyManager); + LogUtil.i("TelephonyMangerCompat.sendVisualVoicemailSms", "using TelephonyManager"); + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(phoneAccountHandle); + return (String) method.invoke(telephonyManager, number, port, text, sentIntent); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -41,16 +53,62 @@ public class TelephonyMangerCompat { // Do nothing, try the next version. } + try { + LogUtil.i("TelephonyMangerCompat.sendVisualVoicemailSms", "using VisualVoicemailService"); + Method method = + VisualVoicemailService.class.getMethod( + "sendVisualVoicemailSms", + Context.class, + PhoneAccountHandle.class, + String.class, + short.class, + String.class, + PendingIntent.class); + return (String) + method.invoke(null, context, phoneAccountHandle, number, (short) port, text, sentIntent); + + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + /** Moved from VisualVoicemailService to TelephonyManager */ + public static String setVisualVoicemailSmsFilterSettings( + Context context, + PhoneAccountHandle phoneAccountHandle, + VisualVoicemailSmsFilterSettings settings) { try { Method method = TelephonyManager.class.getMethod( - GET_VISUAL_VOICEMAIL_PACKGE_NAME, PhoneAccountHandle.class); + "setVisualVoicemailSmsFilterSettings", VisualVoicemailSmsFilterSettings.class); try { - return (String) method.invoke(telephonyManager, (Object) null); + LogUtil.i( + "TelephonyMangerCompat.setVisualVoicemailSmsFilterSettings", "using TelephonyManager"); + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(phoneAccountHandle); + return (String) method.invoke(telephonyManager, settings); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } catch (NoSuchMethodException e) { + // Do nothing, try the next version. + } + + try { + LogUtil.i( + "TelephonyMangerCompat.setVisualVoicemailSmsFilterSettings", + "using VisualVoicemailService"); + Method method = + VisualVoicemailService.class.getMethod( + "setSmsFilterSettings", + Context.class, + PhoneAccountHandle.class, + VisualVoicemailSmsFilterSettings.class); + return (String) method.invoke(null, context, phoneAccountHandle, settings); + + } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } diff --git a/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java b/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java index 04012c9c253972183ef7475f1def4438ae5f059a..b4def2fc3dd417d014cdcca039116237fe65f483 100644 --- a/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java +++ b/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java @@ -16,11 +16,12 @@ package com.android.voicemail.impl; -import android.content.res.Resources; +import android.content.Context; import android.os.PersistableBundle; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.util.ArrayMap; +import com.android.dialer.common.ConfigProviderBindings; import com.android.voicemail.impl.utils.XmlUtils; import java.io.IOException; import java.util.ArrayList; @@ -38,22 +39,24 @@ public class TelephonyVvmConfigManager { private static final String TAG_PERSISTABLEMAP = "pbundle_as_map"; - static final String KEY_MCCMNC = "mccmnc"; + @VisibleForTesting static final String KEY_MCCMNC = "mccmnc"; + + private static final String KEY_FEATURE_FLAG_NAME = "feature_flag_name"; private static Map sCachedConfigs; private final Map mConfigs; - public TelephonyVvmConfigManager(Resources resources) { + public TelephonyVvmConfigManager(Context context) { if (sCachedConfigs == null) { - sCachedConfigs = loadConfigs(resources.getXml(R.xml.vvm_config)); + sCachedConfigs = loadConfigs(context, context.getResources().getXml(R.xml.vvm_config)); } mConfigs = sCachedConfigs; } @VisibleForTesting - TelephonyVvmConfigManager(XmlPullParser parser) { - mConfigs = loadConfigs(parser); + TelephonyVvmConfigManager(Context context, XmlPullParser parser) { + mConfigs = loadConfigs(context, parser); } @Nullable @@ -64,7 +67,7 @@ public class TelephonyVvmConfigManager { return mConfigs.get(mccMnc); } - private static Map loadConfigs(XmlPullParser parser) { + private static Map loadConfigs(Context context, XmlPullParser parser) { Map configs = new ArrayMap<>(); try { ArrayList list = readBundleList(parser); @@ -73,6 +76,13 @@ public class TelephonyVvmConfigManager { throw new IllegalArgumentException("PersistableBundle expected, got " + object); } PersistableBundle bundle = (PersistableBundle) object; + + if (bundle.containsKey(KEY_FEATURE_FLAG_NAME) + && !ConfigProviderBindings.get(context) + .getBoolean(bundle.getString(KEY_FEATURE_FLAG_NAME), false)) { + continue; + } + String[] mccMncs = bundle.getStringArray(KEY_MCCMNC); if (mccMncs == null) { throw new IllegalArgumentException("MCCMNC is null"); diff --git a/java/com/android/voicemail/impl/VoicemailBootReceiver.java b/java/com/android/voicemail/impl/VoicemailBootReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..0a3e61a015072e57a621dc49103784c3437cfd34 --- /dev/null +++ b/java/com/android/voicemail/impl/VoicemailBootReceiver.java @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2017 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.voicemail.impl; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import com.android.voicemail.VoicemailComponent; + +/** Receives {@link Intent#ACTION_BOOT_COMPLETED} for the voicemail module. */ +public class VoicemailBootReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (!VoicemailComponent.get(context).getVoicemailClient().isVoicemailModuleEnabled()) { + return; + } + StatusCheckJobService.schedule(context); + } +} diff --git a/java/com/android/voicemail/impl/VoicemailClientImpl.java b/java/com/android/voicemail/impl/VoicemailClientImpl.java index 31a12791c689dad3f235d666550b40a261a6b7ae..83c0523bfa49e63bb02cc2314a09245a64f94674 100644 --- a/java/com/android/voicemail/impl/VoicemailClientImpl.java +++ b/java/com/android/voicemail/impl/VoicemailClientImpl.java @@ -31,6 +31,7 @@ import com.android.voicemail.VoicemailClient; import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; import com.android.voicemail.impl.settings.VoicemailChangePinActivity; import com.android.voicemail.impl.settings.VoicemailSettingsFragment; +import com.android.voicemail.impl.sync.VvmAccountManager; import java.util.List; import javax.inject.Inject; @@ -67,6 +68,17 @@ public class VoicemailClientImpl implements VoicemailClient { return true; } + @Override + public boolean isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle) { + return VisualVoicemailSettingsUtil.isEnabled(context, phoneAccountHandle); + } + + @Override + public void setVoicemailEnabled( + Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) { + VisualVoicemailSettingsUtil.setEnabled(context, phoneAccountHandle, enabled); + } + @Nullable @Override public String getSettingsFragment() { @@ -85,7 +97,7 @@ public class VoicemailClientImpl implements VoicemailClient { return false; } - if (!ConfigProviderBindings.get(context).getBoolean(ALLOW_VOICEMAIL_ARCHIVE, true)) { + if (!ConfigProviderBindings.get(context).getBoolean(ALLOW_VOICEMAIL_ARCHIVE, false)) { LogUtil.i( "VoicemailClientImpl.isVoicemailArchiveAllowed", "feature disabled by config: %s", @@ -109,12 +121,17 @@ public class VoicemailClientImpl implements VoicemailClient { return intent; } + @Override + public boolean isActivated(Context context, PhoneAccountHandle phoneAccountHandle) { + return VvmAccountManager.isAccountActivated(context, phoneAccountHandle); + } + @TargetApi(VERSION_CODES.O) @Override public void appendOmtpVoicemailSelectionClause( Context context, StringBuilder where, List selectionArgs) { - TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); - String omtpSource = TelephonyMangerCompat.getVisualVoicemailPackageName(telephonyManager); + String omtpSource = + context.getSystemService(TelephonyManager.class).getVisualVoicemailPackageName(); if (where.length() != 0) { where.append(" AND "); } @@ -145,8 +162,8 @@ public class VoicemailClientImpl implements VoicemailClient { @Override public void appendOmtpVoicemailStatusSelectionClause( Context context, StringBuilder where, List selectionArgs) { - TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); - String omtpSource = TelephonyMangerCompat.getVisualVoicemailPackageName(telephonyManager); + String omtpSource = + context.getSystemService(TelephonyManager.class).getVisualVoicemailPackageName(); if (where.length() != 0) { where.append(" AND "); } diff --git a/java/com/android/voicemail/impl/VoicemailModule.java b/java/com/android/voicemail/impl/VoicemailModule.java index c3e5714d5df214ba94683a75c7f845743091b22a..5a4e739f5b10ca8d8a4a3c0d277bd9e781f2b8e3 100644 --- a/java/com/android/voicemail/impl/VoicemailModule.java +++ b/java/com/android/voicemail/impl/VoicemailModule.java @@ -16,8 +16,10 @@ package com.android.voicemail.impl; +import android.content.Context; import android.support.v4.os.BuildCompat; import com.android.voicemail.VoicemailClient; +import com.android.voicemail.VoicemailPermissionHelper; import com.android.voicemail.stub.StubVoicemailClient; import dagger.Module; import dagger.Provides; @@ -29,12 +31,21 @@ public final class VoicemailModule { @Provides @Singleton - static VoicemailClient provideVoicemailClient() { - if (BuildCompat.isAtLeastO()) { - return new VoicemailClientImpl(); - } else { + static VoicemailClient provideVoicemailClient(Context context) { + if (!BuildCompat.isAtLeastO()) { + VvmLog.i("VoicemailModule.provideVoicemailClient", "SDK below O"); return new StubVoicemailClient(); } + + if (!VoicemailPermissionHelper.hasPermissions(context)) { + VvmLog.i( + "VoicemailModule.provideVoicemailClient", + "missing permissions " + VoicemailPermissionHelper.getMissingPermissions(context)); + return new StubVoicemailClient(); + } + + VvmLog.i("VoicemailModule.provideVoicemailClient", "providing VoicemailClientImpl"); + return new VoicemailClientImpl(); } private VoicemailModule() {} diff --git a/java/com/android/voicemail/impl/VvmPackageInstallHandler.java b/java/com/android/voicemail/impl/VvmPackageInstallHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..8d1fb2289bc6da32a0dc20fb6c0ac77d0cb37442 --- /dev/null +++ b/java/com/android/voicemail/impl/VvmPackageInstallHandler.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2017 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.voicemail.impl; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ChangedPackages; +import android.os.Build.VERSION_CODES; +import android.preference.PreferenceManager; +import android.provider.Settings.Global; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.util.ArraySet; +import com.android.dialer.common.PackageUtils; +import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; +import java.util.Set; + +/** + * When a new package is installed, check if it matches any of the vvm carrier apps of the currently + * enabled dialer VVM sources. The dialer VVM client will be disabled upon carrier VVM app + * installation, unless it was explicitly enabled by the user. + * + *

The ACTION_PACKAGE_ADDED broadcast can no longer be received. (see + * https://developer.android.com/preview/features/background.html#broadcasts) New apps are scanned + * when a VVM SMS is received instead, as it can be a result of the carrier VVM app trying to run + * activation. + */ +@SuppressLint("AndroidApiChecker") // forEach +@TargetApi(VERSION_CODES.O) +public final class VvmPackageInstallHandler { + + private static final String LAST_BOOT_COUNT = + "com.android.voicemail.impl.VvmPackageInstallHandler.LAST_BOOT_COUNT"; + + private static final String CHANGED_PACKAGES_SEQUENCE_NUMBER = + "com.android.voicemail.impl.VvmPackageInstallHandler.CHANGED_PACKAGES_SEQUENCE_NUMBER"; + + private static final String INSTALLED_CARRIER_PACKAGES = + "com.android.voicemail.impl.VvmPackageInstallHandler.INSTALLED_CARRIER_PACKAGES"; + + /** + * Perform a scan of all changed apps since the last invocation to see if the carrier VVM app is + * installed. + */ + public static void scanNewPackages(Context context) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + int sequenceNumber = sharedPreferences.getInt(CHANGED_PACKAGES_SEQUENCE_NUMBER, 0); + int lastBootCount = sharedPreferences.getInt(LAST_BOOT_COUNT, 0); + int bootCount = Global.getInt(context.getContentResolver(), Global.BOOT_COUNT, 0); + if (lastBootCount != bootCount) { + VvmLog.i( + "VvmPackageInstallHandler.scanNewPackages", "reboot detected, resetting sequence number"); + sequenceNumber = 0; + sharedPreferences.edit().putInt(LAST_BOOT_COUNT, bootCount).apply(); + } + + ChangedPackages changedPackages = + context.getPackageManager().getChangedPackages(sequenceNumber); + if (changedPackages == null) { + VvmLog.i("VvmPackageInstallHandler.scanNewPackages", "no package has changed"); + return; + } + sharedPreferences + .edit() + .putInt(CHANGED_PACKAGES_SEQUENCE_NUMBER, changedPackages.getSequenceNumber()) + .apply(); + + Set installedPackages = + sharedPreferences.getStringSet(INSTALLED_CARRIER_PACKAGES, new ArraySet<>()); + + Set monitoredPackage = getMonitoredPackages(context); + installedPackages.removeIf((packageName) -> !monitoredPackage.contains(packageName)); + + for (String packageName : changedPackages.getPackageNames()) { + if (!monitoredPackage.contains(packageName)) { + continue; + } + if (PackageUtils.isPackageEnabled(packageName, context)) { + if (!installedPackages.contains(packageName)) { + VvmLog.i("VvmPackageInstallHandler.scanNewPackages", "new package found: " + packageName); + installedPackages.add(packageName); + handlePackageInstalled(context, packageName); + } + } else { + installedPackages.remove(packageName); + } + } + sharedPreferences.edit().putStringSet(INSTALLED_CARRIER_PACKAGES, installedPackages).apply(); + } + + private static Set getMonitoredPackages(Context context) { + Set result = new ArraySet<>(); + context + .getSystemService(TelecomManager.class) + .getCallCapablePhoneAccounts() + .forEach( + (phoneAccountHandle -> { + OmtpVvmCarrierConfigHelper carrierConfigHelper = + new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle); + if (!carrierConfigHelper.isValid()) { + return; + } + if (carrierConfigHelper.getCarrierVvmPackageNames() == null) { + return; + } + result.addAll(carrierConfigHelper.getCarrierVvmPackageNames()); + })); + + return result; + }; + + /** + * Iterates through all phone account and disable VVM on a account if {@code packageName} is + * listed as a carrier VVM package. + */ + private static void handlePackageInstalled(Context context, String packageName) { + // This get called every time an app is installed and will be noisy. Don't log until the app + // is identified as a carrier VVM app. + for (PhoneAccountHandle phoneAccount : + context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) { + OmtpVvmCarrierConfigHelper carrierConfigHelper = + new OmtpVvmCarrierConfigHelper(context, phoneAccount); + if (!carrierConfigHelper.isValid()) { + continue; + } + if (carrierConfigHelper.getCarrierVvmPackageNames() == null) { + continue; + } + if (!carrierConfigHelper.getCarrierVvmPackageNames().contains(packageName)) { + continue; + } + + VvmLog.i("VvmPackageInstallHandler.handlePackageInstalled", "Carrier app installed"); + if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) { + // Skip the check if this voicemail source's setting is overridden by the user. + VvmLog.i( + "VvmPackageInstallHandler.handlePackageInstalled", + "VVM enabled by user, not disabling"); + continue; + } + + // Force deactivate the client. The user can re-enable it in the settings. + // There is no need to update the settings for deactivation. At this point, if the + // default value is used it should be false because a carrier package is present. + VvmLog.i( + "VvmPackageInstallHandler.handlePackageInstalled", + "Carrier VVM package installed, disabling system VVM client"); + VisualVoicemailSettingsUtil.setEnabled(context, phoneAccount, false); + } + } +} diff --git a/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java b/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java index d920121478c44d9dc956402e5bfc54b4e2c5ec3c..1e2de60704d8c95f497b6c1a7dfb9294b2b94005 100644 --- a/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java +++ b/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java @@ -25,7 +25,8 @@ import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; /** * When a new package is installed, check if it matches any of the vvm carrier apps of the currently - * enabled dialer vvm sources. + * enabled dialer VVM sources. The dialer VVM client will be disabled upon carrier VVM app + * installation, unless it was explicitly enabled by the user. */ public class VvmPackageInstallReceiver extends BroadcastReceiver { @@ -46,25 +47,34 @@ public class VvmPackageInstallReceiver extends BroadcastReceiver { return; } + // This get called every time an app is installed and will be noisy. Don't log until the app + // is identified as a carrier VVM app. for (PhoneAccountHandle phoneAccount : context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) { - if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) { - // Skip the check if this voicemail source's setting is overridden by the user. - continue; - } - OmtpVvmCarrierConfigHelper carrierConfigHelper = new OmtpVvmCarrierConfigHelper(context, phoneAccount); + if (!carrierConfigHelper.isValid()) { + continue; + } if (carrierConfigHelper.getCarrierVvmPackageNames() == null) { continue; } - if (carrierConfigHelper.getCarrierVvmPackageNames().contains(packageName)) { - // Force deactivate the client. The user can re-enable it in the settings. - // There is no need to update the settings for deactivation. At this point, if the - // default value is used it should be false because a carrier package is present. - VvmLog.i(TAG, "Carrier VVM package installed, disabling system VVM client"); - VisualVoicemailSettingsUtil.setEnabled(context, phoneAccount, false); + if (!carrierConfigHelper.getCarrierVvmPackageNames().contains(packageName)) { + continue; } + + VvmLog.i(TAG, "Carrier app installed"); + if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) { + // Skip the check if this voicemail source's setting is overridden by the user. + VvmLog.i(TAG, "VVM enabled by user, not disabling"); + continue; + } + + // Force deactivate the client. The user can re-enable it in the settings. + // There is no need to update the settings for deactivation. At this point, if the + // default value is used it should be false because a carrier package is present. + VvmLog.i(TAG, "Carrier VVM package installed, disabling system VVM client"); + VisualVoicemailSettingsUtil.setEnabled(context, phoneAccount, false); } } } diff --git a/java/com/android/voicemail/impl/fetch/FetchVoicemailReceiver.java b/java/com/android/voicemail/impl/fetch/FetchVoicemailReceiver.java index b0285672e906560785abd488bf2e99080f826441..0348a60c58d8b55f9a8badf37af58186ec3d6774 100644 --- a/java/com/android/voicemail/impl/fetch/FetchVoicemailReceiver.java +++ b/java/com/android/voicemail/impl/fetch/FetchVoicemailReceiver.java @@ -120,6 +120,16 @@ public class FetchVoicemailReceiver extends BroadcastReceiver { new PhoneAccountHandle( ComponentName.unflattenFromString(cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME)), cursor.getString(PHONE_ACCOUNT_ID)); + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(mPhoneAccount); + if (telephonyManager == null) { + // can happen when trying to fetch voicemails from a SIM that is no longer on the + // device + VvmLog.e(TAG, "account no longer valid, cannot retrieve message"); + return; + } if (!VvmAccountManager.isAccountActivated(context, mPhoneAccount)) { mPhoneAccount = getAccountFromMarshmallowAccount(context, mPhoneAccount); if (mPhoneAccount == null) { diff --git a/java/com/android/voicemail/impl/imap/ImapHelper.java b/java/com/android/voicemail/impl/imap/ImapHelper.java index 6aa4158116bf8a517731b06e2bd0d20d3ffe571f..f1bc8b221f1c99e63ef97e5b072d86294bba8a91 100644 --- a/java/com/android/voicemail/impl/imap/ImapHelper.java +++ b/java/com/android/voicemail/impl/imap/ImapHelper.java @@ -19,7 +19,7 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkInfo; -import android.provider.VoicemailContract; +import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.util.Base64; import com.android.voicemail.impl.OmtpConstants; @@ -44,6 +44,7 @@ import com.android.voicemail.impl.mail.TempDirectory; import com.android.voicemail.impl.mail.internet.MimeMessage; import com.android.voicemail.impl.mail.store.ImapConnection; import com.android.voicemail.impl.mail.store.ImapFolder; +import com.android.voicemail.impl.mail.store.ImapFolder.Quota; import com.android.voicemail.impl.mail.store.ImapStore; import com.android.voicemail.impl.mail.store.imap.ImapConstants; import com.android.voicemail.impl.mail.store.imap.ImapResponse; @@ -73,11 +74,6 @@ public class ImapHelper implements Closeable { private final Editor mStatus; VisualVoicemailPreferences mPrefs; - private static final String PREF_KEY_QUOTA_OCCUPIED = "quota_occupied_"; - private static final String PREF_KEY_QUOTA_TOTAL = "quota_total_"; - - private int mQuotaOccupied; - private int mQuotaTotal; private final OmtpVvmCarrierConfigHelper mConfig; @@ -90,10 +86,7 @@ public class ImapHelper implements Closeable { } public ImapHelper( - Context context, - PhoneAccountHandle phoneAccount, - Network network, - Editor status) + Context context, PhoneAccountHandle phoneAccount, Network network, Editor status) throws InitializingException { this( context, @@ -139,10 +132,6 @@ public class ImapHelper implements Closeable { LogUtils.w(TAG, "Could not parse port number"); throw new InitializingException("cannot initialize ImapHelper:" + e.toString()); } - - mQuotaOccupied = - mPrefs.getInt(PREF_KEY_QUOTA_OCCUPIED, VoicemailContract.Status.QUOTA_UNAVAILABLE); - mQuotaTotal = mPrefs.getInt(PREF_KEY_QUOTA_TOTAL, VoicemailContract.Status.QUOTA_UNAVAILABLE); } @Override @@ -475,12 +464,22 @@ public class ImapHelper implements Closeable { } } - public int getOccuupiedQuota() { - return mQuotaOccupied; - } - - public int getTotalQuota() { - return mQuotaTotal; + @Nullable + public Quota getQuota() { + try { + mFolder = openImapFolder(ImapFolder.MODE_READ_ONLY); + if (mFolder == null) { + // This means we were unable to successfully open the folder. + LogUtils.e(TAG, "Unable to open folder"); + return null; + } + return mFolder.getQuota(); + } catch (MessagingException e) { + LogUtils.e(TAG, e, "Messaging Exception"); + return null; + } finally { + closeImapFolder(); + } } private void updateQuota(ImapFolder folder) throws MessagingException { @@ -489,21 +488,19 @@ public class ImapHelper implements Closeable { private void setQuota(ImapFolder.Quota quota) { if (quota == null) { + LogUtils.i(TAG, "quota was null"); return; } - if (quota.occupied == mQuotaOccupied && quota.total == mQuotaTotal) { - VvmLog.v(TAG, "Quota hasn't changed"); - return; - } - mQuotaOccupied = quota.occupied; - mQuotaTotal = quota.total; - VoicemailStatus.edit(mContext, mPhoneAccount).setQuota(mQuotaOccupied, mQuotaTotal).apply(); - mPrefs - .edit() - .putInt(PREF_KEY_QUOTA_OCCUPIED, mQuotaOccupied) - .putInt(PREF_KEY_QUOTA_TOTAL, mQuotaTotal) - .apply(); - VvmLog.v(TAG, "Quota changed to " + mQuotaOccupied + "/" + mQuotaTotal); + + LogUtils.i( + TAG, + "Updating Voicemail status table with" + + " quota occupied: " + + quota.occupied + + " new quota total:" + + quota.total); + VoicemailStatus.edit(mContext, mPhoneAccount).setQuota(quota.occupied, quota.total).apply(); + LogUtils.i(TAG, "Updated quota occupied and total"); } /** diff --git a/java/com/android/voicemail/impl/mail/Address.java b/java/com/android/voicemail/impl/mail/Address.java index 3a7a8660712c42fc94464fe431b668915952fc7c..ac8e8a2941bf90cca1b413ef3d863a461c9181ca 100644 --- a/java/com/android/voicemail/impl/mail/Address.java +++ b/java/com/android/voicemail/impl/mail/Address.java @@ -25,8 +25,9 @@ import android.text.util.Rfc822Tokenizer; import com.android.voicemail.impl.mail.utils.LogUtils; import java.util.ArrayList; import java.util.regex.Pattern; +import org.apache.james.mime4j.codec.DecodeMonitor; +import org.apache.james.mime4j.codec.DecoderUtil; import org.apache.james.mime4j.codec.EncoderUtil; -import org.apache.james.mime4j.decoder.DecoderUtil; /** * This class represent email address. @@ -121,7 +122,8 @@ public class Address implements Parcelable { if (TextUtils.isEmpty(rawAddress)) { return null; } - String name, address; + String name; + String address; final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(rawAddress); if (tokens.length > 0) { final String tokenizedName = tokens[0].getName(); @@ -171,7 +173,7 @@ public class Address implements Parcelable { if (personal != null) { personal = REMOVE_OPTIONAL_DQUOTE.matcher(personal).replaceAll("$1"); personal = UNQUOTE.matcher(personal).replaceAll("$1"); - personal = DecoderUtil.decodeEncodedWords(personal); + personal = DecoderUtil.decodeEncodedWords(personal, DecodeMonitor.STRICT); if (personal.length() == 0) { personal = null; } diff --git a/java/com/android/voicemail/impl/mail/internet/MimeMessage.java b/java/com/android/voicemail/impl/mail/internet/MimeMessage.java index dfb7d7c25a83fc9760543a649784539fb480b78d..58972066035056b17f5d28312a98f9b7b07383e6 100644 --- a/java/com/android/voicemail/impl/mail/internet/MimeMessage.java +++ b/java/com/android/voicemail/impl/mail/internet/MimeMessage.java @@ -34,12 +34,14 @@ import java.util.Date; import java.util.Locale; import java.util.Stack; import java.util.regex.Pattern; -import org.apache.james.mime4j.BodyDescriptor; -import org.apache.james.mime4j.ContentHandler; -import org.apache.james.mime4j.EOLConvertingInputStream; -import org.apache.james.mime4j.MimeStreamParser; -import org.apache.james.mime4j.field.DateTimeField; -import org.apache.james.mime4j.field.Field; +import org.apache.james.mime4j.MimeException; +import org.apache.james.mime4j.dom.field.DateTimeField; +import org.apache.james.mime4j.field.DefaultFieldParser; +import org.apache.james.mime4j.io.EOLConvertingInputStream; +import org.apache.james.mime4j.parser.ContentHandler; +import org.apache.james.mime4j.parser.MimeStreamParser; +import org.apache.james.mime4j.stream.BodyDescriptor; +import org.apache.james.mime4j.stream.Field; /** * An implementation of Message that stores all of its metadata in RFC 822 and RFC 2045 style @@ -64,7 +66,6 @@ public class MimeMessage extends Message { private Body mBody; protected int mSize; private boolean mInhibitLocalMessageId = false; - private boolean mComplete = true; // Shared random source for generating local message-id values private static final java.util.Random sRandom = new java.util.Random(); @@ -114,7 +115,7 @@ public class MimeMessage extends Message { * @throws IOException * @throws MessagingException */ - public MimeMessage(InputStream in) throws IOException, MessagingException { + public MimeMessage(InputStream in) throws IOException, MessagingException, MimeException { parse(in); } @@ -136,17 +137,9 @@ public class MimeMessage extends Message { return parser; } - protected void parse(InputStream in) throws IOException, MessagingException { + public void parse(InputStream in) throws IOException, MessagingException, MimeException { final MimeStreamParser parser = init(); parser.parse(new EOLConvertingInputStream(in)); - mComplete = !parser.getPrematureEof(); - } - - public void parse(InputStream in, EOLConvertingInputStream.Callback callback) - throws IOException, MessagingException { - final MimeStreamParser parser = init(); - parser.parse(new EOLConvertingInputStream(in, getSize(), callback)); - mComplete = !parser.getPrematureEof(); } /** @@ -171,7 +164,8 @@ public class MimeMessage extends Message { try { DateTimeField field = (DateTimeField) - Field.parse("Date: " + MimeUtility.unfoldAndDecode(getFirstHeader("Date"))); + DefaultFieldParser.parse( + "Date: " + MimeUtility.unfoldAndDecode(getFirstHeader("Date"))); mSentDate = field.getDate(); // TODO: We should make it more clear what exceptions can be thrown here, // and whether they reflect a normal or error condition. @@ -184,7 +178,7 @@ public class MimeMessage extends Message { try { DateTimeField field = (DateTimeField) - Field.parse( + DefaultFieldParser.parse( "Date: " + MimeUtility.unfoldAndDecode(getFirstHeader("Delivery-date"))); mSentDate = field.getDate(); // TODO: We should make it more clear what exceptions can be thrown here, @@ -228,10 +222,6 @@ public class MimeMessage extends Message { } } - public boolean isComplete() { - return mComplete; - } - @Override public String getMimeType() throws MessagingException { return MimeUtility.getHeaderParameter(getContentType(), null); @@ -577,10 +567,10 @@ public class MimeMessage extends Message { } @Override - public void field(String fieldData) { + public void field(Field rawField) { expect(Part.class); try { - final String[] tokens = fieldData.split(":", 2); + final String[] tokens = rawField.getRaw().toString().split(":", 2); ((Part) stack.peek()).addHeader(tokens[0], tokens[1].trim()); } catch (MessagingException me) { throw new Error(me); diff --git a/java/com/android/voicemail/impl/mail/internet/MimeUtility.java b/java/com/android/voicemail/impl/mail/internet/MimeUtility.java index 99846027b14373c8a4acc1ddff1349e0c557e9cb..bd85e478c7e4f822b60320baa02f7deeb5584415 100644 --- a/java/com/android/voicemail/impl/mail/internet/MimeUtility.java +++ b/java/com/android/voicemail/impl/mail/internet/MimeUtility.java @@ -34,9 +34,10 @@ import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; +import org.apache.james.mime4j.codec.DecodeMonitor; +import org.apache.james.mime4j.codec.DecoderUtil; import org.apache.james.mime4j.codec.EncoderUtil; -import org.apache.james.mime4j.decoder.DecoderUtil; -import org.apache.james.mime4j.decoder.QuotedPrintableInputStream; +import org.apache.james.mime4j.codec.QuotedPrintableInputStream; import org.apache.james.mime4j.util.CharsetUtil; public class MimeUtility { @@ -65,7 +66,7 @@ public class MimeUtility { if (s == null) { return null; } - return DecoderUtil.decodeEncodedWords(s); + return DecoderUtil.decodeEncodedWords(s, DecodeMonitor.STRICT); } public static String unfoldAndDecode(String s) { @@ -235,7 +236,7 @@ public class MimeUtility { /* * See if there is conversion from the MIME charset to the Java one. */ - charset = CharsetUtil.toJavaCharset(charset); + charset = CharsetUtil.lookup(charset).name(); } /* * No encoding, so use us-ascii, which is the standard. diff --git a/java/com/android/voicemail/impl/mail/store/ImapFolder.java b/java/com/android/voicemail/impl/mail/store/ImapFolder.java index 1d9b01120a5d0304015cc9ae65d74aad78d81c63..5760ee2165820ccf1832109aab4d0eec4d95e898 100644 --- a/java/com/android/voicemail/impl/mail/store/ImapFolder.java +++ b/java/com/android/voicemail/impl/mail/store/ImapFolder.java @@ -22,6 +22,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Base64DataException; import com.android.voicemail.impl.OmtpEvents; +import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.mail.AuthenticationFailedException; import com.android.voicemail.impl.mail.Body; import com.android.voicemail.impl.mail.FetchProfile; @@ -41,7 +42,6 @@ import com.android.voicemail.impl.mail.store.imap.ImapElement; import com.android.voicemail.impl.mail.store.imap.ImapList; import com.android.voicemail.impl.mail.store.imap.ImapResponse; import com.android.voicemail.impl.mail.store.imap.ImapString; -import com.android.voicemail.impl.mail.utils.LogUtils; import com.android.voicemail.impl.mail.utils.Utility; import java.io.IOException; import java.io.InputStream; @@ -66,7 +66,7 @@ public class ImapFolder { private String mMode; private boolean mExists; /** A set of hashes that can be used to track dirtiness */ - Object mHash[]; + Object[] mHash; public static final String MODE_READ_ONLY = "mode_read_only"; public static final String MODE_READ_WRITE = "mode_read_write"; @@ -136,7 +136,7 @@ public class ImapFolder { try { expunge(); } catch (MessagingException e) { - LogUtils.e(TAG, e, "Messaging Exception"); + VvmLog.e(TAG, "Messaging Exception", e); } } mMessageCount = -1; @@ -174,13 +174,13 @@ public class ImapFolder { try { final String command = ImapConstants.UID_SEARCH + " " + searchCriteria; final String[] result = getSearchUids(mConnection.executeSimpleCommand(command)); - LogUtils.d(TAG, "searchForUids '" + searchCriteria + "' results: " + result.length); + VvmLog.d(TAG, "searchForUids '" + searchCriteria + "' results: " + result.length); return result; } catch (ImapException me) { - LogUtils.d(TAG, "ImapException in search: " + searchCriteria, me); + VvmLog.d(TAG, "ImapException in search: " + searchCriteria, me); return Utility.EMPTY_STRINGS; // Not found } catch (IOException ioe) { - LogUtils.d(TAG, "IOException in search: " + searchCriteria, ioe); + VvmLog.d(TAG, "IOException in search: " + searchCriteria, ioe); mStore.getImapHelper().handleEvent(OmtpEvents.DATA_GENERIC_IMAP_IOE); throw ioExceptionHandler(mConnection, ioe); } @@ -199,7 +199,7 @@ public class ImapFolder { return new ImapMessage(uid, this); } } - LogUtils.e(TAG, "UID " + uid + " not found on server"); + VvmLog.e(TAG, "UID " + uid + " not found on server"); return null; } @@ -235,7 +235,7 @@ public class ImapFolder { try { fetchInternal(messages, fp, listener); } catch (RuntimeException e) { // Probably a parser error. - LogUtils.w(TAG, "Exception detected: " + e.getMessage()); + VvmLog.w(TAG, "Exception detected: " + e.getMessage()); throw e; } } @@ -346,7 +346,11 @@ public class ImapFolder { message.setInternalDate(internalDate); message.setSize(size); - message.parse(Utility.streamFromAsciiString(header)); + try { + message.parse(Utility.streamFromAsciiString(header)); + } catch (Exception e) { + VvmLog.e(TAG, "Error parsing header %s", e); + } } if (fp.contains(FetchProfile.Item.STRUCTURE)) { ImapList bs = fetchList.getKeyedListOrEmpty(ImapConstants.BODYSTRUCTURE); @@ -354,7 +358,7 @@ public class ImapFolder { try { parseBodyStructure(bs, message, ImapConstants.TEXT); } catch (MessagingException e) { - LogUtils.v(TAG, e, "Error handling message"); + VvmLog.v(TAG, "Error handling message", e); message.setBody(null); } } @@ -365,11 +369,15 @@ public class ImapFolder { // TODO Should we accept "RFC822" as well?? ImapString body = fetchList.getKeyedStringOrEmpty("BODY[]", true); InputStream bodyStream = body.getAsStream(); - message.parse(bodyStream); + try { + message.parse(bodyStream); + } catch (Exception e) { + VvmLog.e(TAG, "Error parsing body %s", e); + } } if (fetchPart != null) { InputStream bodyStream = fetchList.getKeyedStringOrEmpty("BODY[", true).getAsStream(); - String encodings[] = fetchPart.getHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING); + String[] encodings = fetchPart.getHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING); String contentTransferEncoding = null; if (encodings != null && encodings.length > 0) { @@ -397,7 +405,7 @@ public class ImapFolder { // from here. This blanket catch-all is because we're not sure what to // do if we don't have a contentTransferEncoding, and we don't have // time to figure out what exceptions might be thrown. - LogUtils.e(TAG, "Error fetching body %s", e); + VvmLog.e(TAG, "Error fetching body %s", e); } } @@ -782,7 +790,7 @@ public class ImapFolder { } private MessagingException ioExceptionHandler(ImapConnection connection, IOException ioe) { - LogUtils.d(TAG, "IO Exception detected: ", ioe); + VvmLog.d(TAG, "IO Exception detected: ", ioe); connection.close(); if (connection == mConnection) { mConnection = null; // To prevent close() from returning the connection to the pool. diff --git a/java/com/android/voicemail/impl/mail/store/ImapStore.java b/java/com/android/voicemail/impl/mail/store/ImapStore.java index cadbe593f77fda5f8d009b11a5052c33bd4e59ff..838bae2574a1052bdcd2a280be45e2f24df7fb64 100644 --- a/java/com/android/voicemail/impl/mail/store/ImapStore.java +++ b/java/com/android/voicemail/impl/mail/store/ImapStore.java @@ -25,6 +25,7 @@ import com.android.voicemail.impl.mail.MessagingException; import com.android.voicemail.impl.mail.internet.MimeMessage; import java.io.IOException; import java.io.InputStream; +import org.apache.james.mime4j.MimeException; public class ImapStore { /** @@ -112,7 +113,7 @@ public class ImapStore { } @Override - public void parse(InputStream in) throws IOException, MessagingException { + public void parse(InputStream in) throws IOException, MessagingException, MimeException { super.parse(in); } diff --git a/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java b/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java index 5a720c6099e830d7d51518f7f8c9535cfdafdf86..fc7fdf3d40f2094082bc12fa40d7e3d941c05e4c 100644 --- a/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java +++ b/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java @@ -25,8 +25,7 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; -import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.DialerImpression; import com.android.voicemail.impl.ActivationTask; import com.android.voicemail.impl.OmtpConstants; import com.android.voicemail.impl.OmtpEvents; @@ -45,6 +44,7 @@ import com.android.voicemail.impl.sms.Vvm3MessageSender; import com.android.voicemail.impl.sync.VvmNetworkRequest; import com.android.voicemail.impl.sync.VvmNetworkRequest.NetworkWrapper; import com.android.voicemail.impl.sync.VvmNetworkRequest.RequestFailedException; +import com.android.voicemail.impl.utils.LoggerUtils; import java.io.IOException; import java.security.SecureRandom; import java.util.Locale; @@ -116,7 +116,8 @@ public class Vvm3Protocol extends VisualVoicemailProtocol { StatusMessage message, Bundle data) { VvmLog.i(TAG, "start vvm3 provisioning"); - Logger.get(config.getContext()).logImpression(DialerImpression.Type.VVM_PROVISIONING_STARTED); + LoggerUtils.logImpressionOnMainThread( + config.getContext(), DialerImpression.Type.VVM_PROVISIONING_STARTED); if (OmtpConstants.SUBSCRIBER_UNKNOWN.equals(message.getProvisioningStatus())) { VvmLog.i(TAG, "Provisioning status: Unknown"); if (VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE.equals(message.getReturnCode())) { @@ -229,8 +230,8 @@ public class Vvm3Protocol extends VisualVoicemailProtocol { // Only close new user tutorial if the PIN has been changed. helper.closeNewUserTutorial(); VvmLog.i(TAG, "new user: NUT closed"); - Logger.get(config.getContext()) - .logImpression(DialerImpression.Type.VVM_PROVISIONING_COMPLETED); + LoggerUtils.logImpressionOnMainThread( + config.getContext(), DialerImpression.Type.VVM_PROVISIONING_COMPLETED); config.requestStatus(null); } } catch (InitializingException | MessagingException | IOException e) { diff --git a/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java b/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java index c8a74c8d53c731b9455a1cdb166b11592e023a7a..1cdbbfbca038e346d4f84c23bc0a8315bf60e82d 100644 --- a/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java +++ b/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java @@ -17,10 +17,13 @@ package com.android.voicemail.impl.protocol; import android.annotation.TargetApi; +import android.content.Context; import android.net.Network; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; @@ -28,6 +31,7 @@ import android.text.Html; import android.text.Spanned; import android.text.style.URLSpan; import android.util.ArrayMap; +import com.android.dialer.common.ConfigProviderBindings; import com.android.voicemail.impl.ActivationTask; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.OmtpEvents; @@ -49,6 +53,8 @@ import java.net.CookieHandler; import java.net.CookieManager; import java.net.HttpURLConnection; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; @@ -57,6 +63,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.json.JSONArray; +import org.json.JSONException; /** * Class to subscribe to basic VVM3 visual voicemail, for example, Verizon. Subscription is required @@ -111,7 +119,15 @@ public class Vvm3Subscriber { private static final String SPG_LANGUAGE_PARAM = "SPG_LANGUAGE_PARAM"; private static final String SPG_LANGUAGE_EN = "ENGLISH"; - private static final String BASIC_SUBSCRIBE_LINK_TEXT = "Subscribe to Basic Visual Voice Mail"; + @VisibleForTesting + static final String VVM3_SUBSCRIBE_LINK_PATTERNS_JSON_ARRAY = + "vvm3_subscribe_link_pattern_json_array"; + + private static final String VVM3_SUBSCRIBE_LINK_DEFAULT_PATTERNS = + "[" + + "\"(?i)Subscribe to Basic Visual Voice Mail\"," + + "\"(?i)Subscribe to Basic Visual Voicemail\"" + + "]"; private static final int REQUEST_TIMEOUT_SECONDS = 30; @@ -125,7 +141,8 @@ public class Vvm3Subscriber { private RequestQueue mRequestQueue; - private static class ProvisioningException extends Exception { + @VisibleForTesting + static class ProvisioningException extends Exception { public ProvisioningException(String message) { super(message); @@ -188,7 +205,8 @@ public class Vvm3Subscriber { try { String gatewayUrl = getSelfProvisioningGateway(); String selfProvisionResponse = getSelfProvisionResponse(gatewayUrl); - String subscribeLink = findSubscribeLink(selfProvisionResponse); + String subscribeLink = + findSubscribeLink(getSubscribeLinkPatterns(mHelper.getContext()), selfProvisionResponse); clickSubscribeLink(subscribeLink); } catch (ProvisioningException e) { VvmLog.e(TAG, e.toString()); @@ -291,14 +309,40 @@ public class Vvm3Subscriber { } } - private String findSubscribeLink(String response) throws ProvisioningException { + @VisibleForTesting + static List getSubscribeLinkPatterns(Context context) { + String patternsJsonString = + ConfigProviderBindings.get(context) + .getString( + VVM3_SUBSCRIBE_LINK_PATTERNS_JSON_ARRAY, VVM3_SUBSCRIBE_LINK_DEFAULT_PATTERNS); + List patterns = new ArrayList<>(); + try { + JSONArray patternsArray = new JSONArray(patternsJsonString); + for (int i = 0; i < patternsArray.length(); i++) { + patterns.add(Pattern.compile(patternsArray.getString(i))); + } + } catch (JSONException e) { + throw new IllegalArgumentException("Unable to parse patterns" + e); + } + return patterns; + } + + @VisibleForTesting + static String findSubscribeLink(@NonNull List patterns, String response) + throws ProvisioningException { + if (patterns.isEmpty()) { + throw new IllegalArgumentException("empty patterns"); + } Spanned doc = Html.fromHtml(response, Html.FROM_HTML_MODE_LEGACY); URLSpan[] spans = doc.getSpans(0, doc.length(), URLSpan.class); StringBuilder fulltext = new StringBuilder(); + for (URLSpan span : spans) { String text = doc.subSequence(doc.getSpanStart(span), doc.getSpanEnd(span)).toString(); - if (BASIC_SUBSCRIBE_LINK_TEXT.equals(text)) { - return span.getURL(); + for (Pattern pattern : patterns) { + if (pattern.matcher(text).matches()) { + return span.getURL(); + } } fulltext.append(text); } diff --git a/java/com/android/voicemail/impl/res/values-af/strings.xml b/java/com/android/voicemail/impl/res/values-af/strings.xml index b209eea0dbea0999e6c37514f5435565b6764037..a84553480cf7463e2434d5ddf0eb39360cc8ba67 100644 --- a/java/com/android/voicemail/impl/res/values-af/strings.xml +++ b/java/com/android/voicemail/impl/res/values-af/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Stemboodskap (%s)" "Stemboodskap" - "Vibreer" - "Vibreer" - "Klank" + + "Gevorderde instellings" "Visuele stemboodskap" "Ekstra rugsteun en berging" - " ""Dit is \'n eksperimentele kenmerk"" wat ons tans toets. Dit kan potensieel stemboodskappe van jou stemboodskapbediener af uitvee. Daar is geen waarborg dat hierdie kenmerk in die toekoms gesteun sal word nie. Ons sal egter graag terugvoer oor die kenmerk wil hê." "Stel PIN" "Verander PIN" "Visuele stemboodskap moet geaktiveer wees om PIN te verander" diff --git a/java/com/android/voicemail/impl/res/values-am/strings.xml b/java/com/android/voicemail/impl/res/values-am/strings.xml index 4124de5f7248a16edbe1bbe30fcea3cfb4481b7f..2f0719a0b63dda922d01fe9db9d625f89d752b7a 100644 --- a/java/com/android/voicemail/impl/res/values-am/strings.xml +++ b/java/com/android/voicemail/impl/res/values-am/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "የድምፅ መልዕክት (%s)" "የድምፅ መልዕክት" - "ንዘር" - "ንዘር" - "ድምፅ" + + "የላቁ ቅንብሮች" "ምስላዊ የድምፅ መልዕክት" "ተጨማሪ ምትኬ እና ማከማቻ" - " ""ይህ የሙከራ ባህሪ ነው"" አሁን እየሞከርን ነው። ይህ ምናልባት ከድምፅ መልዕክት አገልጋይዎ ላይ የድምፅ መልዕክቶችን ሊሰርዝ ይችላል። ለወደፊቱ ይህን ባህሪ የመደገፍ ዋስትናዎችም የሉም። ነገር ግን በባህሪው ላይ ግብረመልስ ብናገኝ እንወዳለን።" "ፒን ያዘጋጁ" "ፒን ይቀይሩ" "ፒን ለመቀየር የእይታ የድምጽ መልዕክት መንቃት አለበት" diff --git a/java/com/android/voicemail/impl/res/values-ar/strings.xml b/java/com/android/voicemail/impl/res/values-ar/strings.xml index 5d6fbba3724c649edd06eb81efd2fac7e0fc0bb6..f46ebe1be83e3c03e8f6bdb84f04d3b9411d671a 100644 --- a/java/com/android/voicemail/impl/res/values-ar/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ar/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "البريد الصوتي (%s)" "البريد الصوتي" - "اهتزاز" - "اهتزاز" - "صوت" + + "الإعدادات المتقدمة" "بريد صوتي مرئي" "نسخة احتياطية وسعة تخزين إضافية" - " ""هذه الميزة تجريبية"" نحن حاليًا في مرحلة اختبار. سيؤدي هذا على الأرجح إلى حذف رسائل البريد الصوتي من خادم البريد الصوتي. لا توجد أي ضمانات بشأن دعم هذه الميزة مستقبلاً. إلا أننا نود الحصول على تعليقات بشأن هذه الميزة." "تعيين رقم التعريف الشخصي" "تغيير رقم التعريف الشخصي" "ينبغي تشغيل البريد الصوتي المرئي لتغيير رقم التعريف الشخصي" diff --git a/java/com/android/voicemail/impl/res/values-az/strings.xml b/java/com/android/voicemail/impl/res/values-az/strings.xml index ce68f996307386d4bfc528ebcce1c96eeea09424..ebb85dce89b5e41d77afb173e697a6964199ae9b 100644 --- a/java/com/android/voicemail/impl/res/values-az/strings.xml +++ b/java/com/android/voicemail/impl/res/values-az/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Səsli e-poçt (%s)" "Səsli e-poçt" - "Vibrasiya" - "Vibrasiya" - "Səs" + + "Qabaqcıl Ayarlar" "Görünən Səsli e-poçt" "Əlavə yedəkləmə və yaddaş" - " Bu, hazırda yoxladığımız ""eksperimantal funksiyadır"". Bununla səsli e-poçt serverindən səsli e-məktublar potensial olaraq silinəcək. Gələcəkdə bu funksiyanın dəstəklənəcəyinə zəmanət verilmir. Lakin funksiya haqqında əks əlaqənizi istərdik." "PIN ayarlayın" "PIN-i dəyişin" "PIN-i dəyişmək üçün görünən səsli e-poçt aktiv olmalıdır" diff --git a/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml b/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..41294300b5499add21b953e438bbea3696f4937c --- /dev/null +++ b/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,52 @@ + + + + + "Govorna pošta (%s)" + "Govorna pošta" + + + "Napredna podešavanja" + "Vizuelna govorna pošta" + "Dodatne rezervne kopije i prostor" + "Podesite PIN" + "Promenite PIN" + "Morate da omogućite vizuelnu govornu poštu da biste promenili PIN" + "Vizuelna govorna pošta još uvek nije aktivirana, probajte ponovo kasnije" + "Stari PIN" + "Novi PIN" + "Sačekajte." + "Novi PIN je prekratak." + "Novi PIN je predugačak." + "Novi PIN je preslab. Jaka lozinka ne treba da sadrži uzastopni niz ni ponovljene cifre." + "Stari PIN se ne podudara." + "Novi PIN sadrži nevažeće znakove." + "Promena PIN-a nije uspela" + "Nepodržani tip poruke. Pozovite %s da biste je preslušali." + "Promenite PIN kôd govorne pošte" + "Nastavi" + "Otkaži" + "Potvrdi" + "Potvrdite stari PIN" + "Unesite PIN kôd govorne pošte da biste nastavili." + "Podesite novi PIN" + "Broj cifara koje PIN mora da sadrži: %1$d%2$d." + "Potvrdite PIN" + "PIN-ovi se ne podudaraju" + "PIN kôd govorne pošte je ažuriran" + "Podešavanje PIN-a nije uspelo" + diff --git a/java/com/android/voicemail/impl/res/values-be/strings.xml b/java/com/android/voicemail/impl/res/values-be/strings.xml index ea4a00ca042806936181d5b8cdbab9fbb8a1dc9f..ffb7caba0f17c1f1c4a28860ac8e4827aea85392 100644 --- a/java/com/android/voicemail/impl/res/values-be/strings.xml +++ b/java/com/android/voicemail/impl/res/values-be/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Галасавая пошта (%s)" "Галасавая пошта" - "Вібрацыя" - "Вібрацыя" - "Гук" + + "Пашыраныя налады" "Візуальная галасавая пошта" "Дадатковае рэзервовае капір. і сховішча" - " ""Гэта эксперыментальная характарыстыка"", якую мы тэсціруем. Патэнцыяльна яна будзе выдаляць паведамленні галасавой пошты з вашага сервера галасавой пошты. Падтрымка гэтай характарыстыкі ў будучым не гарантуецца. Але мы будзем вельмі ўдзячны за водгукі на гэту характарыстыку." "Задаць PIN-код" "Змяніць PIN-код" "Трэба ўключыць візуальную галасавую пошту, каб змяніць PIN-код" diff --git a/java/com/android/voicemail/impl/res/values-bg/strings.xml b/java/com/android/voicemail/impl/res/values-bg/strings.xml index 95cc05f36b22dc1582ce321650dd18f18be5e430..d3a66a41c440bbdfd829278d8eb59bd6d5fc865e 100644 --- a/java/com/android/voicemail/impl/res/values-bg/strings.xml +++ b/java/com/android/voicemail/impl/res/values-bg/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Гласова поща (%s)" "Гласова поща" - "Вибриране" - "Вибриране" - "Звук" + + "Разширени настройки" "Визуална гласова поща" "Допълнителни резервни копия и хранилище" - " ""Това е експериментална функция"", която тестваме понастоящем. Тя потенциално може да изтрие гласови съобщения от сървъра ви за гласова поща. Няма гаранции за поддръжката й в бъдеще. Но ще се радваме на отзиви за нея." "Задаване на ПИН код" "Промяна на ПИН кода" "За промяна на ПИН кода трябва да бъде активирана визуалната гласова поща" diff --git a/java/com/android/voicemail/impl/res/values-bn/strings.xml b/java/com/android/voicemail/impl/res/values-bn/strings.xml index dbbeb4d9f6afe1abb2726efc6722c59862456fdc..636f332cb7b2c7882b2656b15b4e920ca768aa1b 100644 --- a/java/com/android/voicemail/impl/res/values-bn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-bn/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ভয়েসমেল (%s)" "ভয়েসমেল" - "কম্পন" - "কম্পন" - "শব্দ" + + "উন্নত সেটিংস" "ভিজ্যুয়াল ভয়েসমেল" "অতিরিক্ত ব্যাক আপ এবং সঞ্চয়স্থান" - " ""এটি একটি পরীক্ষামূলক বৈশিষ্ট্য"" যা আমরা বর্তমানে পরীক্ষা করছি। এটি সম্ভবত আপনার ভয়েসমেল সার্ভার থেকে ভয়েসমেলগুলি মুছবে। যদিও ভবিষ্যতে এই বৈশিষ্ট্যতে সমর্থন পাওয়ার কোন গ্যারান্টি নেই। যদিও আমরা এই বৈশিষ্ট্যটির উপর মতামত পেলে খুব খুশি হব।" "পিন সেট করুন" "পিন পরিবর্তন করুন" "পিন পরিবর্তন করতে ভিজ্যুয়াল ভয়েসমেল অবশ্যই সক্ষম করতে হবে" diff --git a/java/com/android/voicemail/impl/res/values-bs/strings.xml b/java/com/android/voicemail/impl/res/values-bs/strings.xml index 6d2b5b30c28d03a697090c91a5672c99ab5b7dd9..09b9ab6d13457b4d6236959d3b074e29fc96b3a5 100644 --- a/java/com/android/voicemail/impl/res/values-bs/strings.xml +++ b/java/com/android/voicemail/impl/res/values-bs/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Govorna pošta (%s)" "Govorna pošta" - "Vibracija" - "Vibracija" - "Zvuk" + + "Napredne postavke" "Vizuelna govorna pošta" "Dodatna sigurnosna kopija i pohrana" - " ""Ovo je eksperimentalna funkcija"" koju trenutno testiramo. Moguće je da ova radnja izbriše poruke govorne pošte sa servera govorne pošte. Nema garancije da će ova funkcija biti podržana u budućnosti. Ipak bismo željeli primiti povratne informacije o funkciji." "Postavite PIN kôd" "Promijenite PIN kôd" "Vizuelna govorna pošta mora biti omogućena za promjenu PIN kôda" diff --git a/java/com/android/voicemail/impl/res/values-ca/strings.xml b/java/com/android/voicemail/impl/res/values-ca/strings.xml index bbac25294fdaabb8c7662248397caa748f1425a5..e6c3bc73098c927a8b1742220b304353cce19153 100644 --- a/java/com/android/voicemail/impl/res/values-ca/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ca/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Bústia de veu (%s)" "Bústia de veu" - "Vibra" - "Vibra" - "So" + + "Configuració avançada" "Bústia de veu visual" "Còpia de seguretat addicional i emmagatz." - " ""Aquesta funció està en mode de prova"" i és possible que suprimeixi els missatges de veu del servidor de la bústia. No podem garantir-ne la continuïtat en el futur. De tota manera, ens agradaria saber què en penses." "Defineix el PIN" "Canvia el PIN" "La bústia de veu visual ha d\'estar activada per poder canviar el PIN" diff --git a/java/com/android/voicemail/impl/res/values-cs/strings.xml b/java/com/android/voicemail/impl/res/values-cs/strings.xml index fb6be6cf4ca4bdcdf8e4e03f179d75b17313e113..621c4a8b1669e0d724af93fc3b0de784a384eb6c 100644 --- a/java/com/android/voicemail/impl/res/values-cs/strings.xml +++ b/java/com/android/voicemail/impl/res/values-cs/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Hlasová schránka (%s)" "Hlasová schránka" - "Vibrace" - "Vibrace" - "Zvuk" + + "Pokročilá nastavení" "Vizuální hlasová schránka" "Další zálohování a úložiště" - " ""Toto je experimentální funkce"", kterou právě testujeme. Funkce vám může smazat hlasové zprávy ze serveru hlasové schránky. Nemůžeme zaručit, že bude podporována i v budoucnu, budeme vám ale vděční za zpětnou vazbu." "Nastavit kód PIN" "Změnit kód PIN" "Pokud chcete kód PIN změnit, musíte mít zapnutou vizuální hlasovou schránku" diff --git a/java/com/android/voicemail/impl/res/values-da/strings.xml b/java/com/android/voicemail/impl/res/values-da/strings.xml index 760c3bc39e36eda6d72d9b6c0bd966a7d8945d42..e9f0404d2a431118c70e160a340f0ffa3f0ef641 100644 --- a/java/com/android/voicemail/impl/res/values-da/strings.xml +++ b/java/com/android/voicemail/impl/res/values-da/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Telefonsvarer (%s)" "Telefonsvarer" - "Vibrer" - "Vibrer" - "Lyd" + + "Avancerede indstillinger" "Visuel telefonsvarer" "Ekstra sikkerhedskopiering og lagerplads" - " ""Dette er en eksperimental funktion,"" som vi tester i øjeblikket. Der slettes måske talebeskeder fra din telefonsvarerserver. Der er ingen garanti for, at denne funktion understøttes fremover. Vi vil dog stadig gerne have feedback om funktionen." "Angiv pinkode" "Skift pinkode" "Visuel telefonsvarer skal være aktiveret, for at du kan skifte pinkode" diff --git a/java/com/android/voicemail/impl/res/values-de/strings.xml b/java/com/android/voicemail/impl/res/values-de/strings.xml index bc5c70f5e696f1d6fe632800baa67cafb77ed680..c4cc75b37d7b1819e1e05a04ba2fa20a283115dd 100644 --- a/java/com/android/voicemail/impl/res/values-de/strings.xml +++ b/java/com/android/voicemail/impl/res/values-de/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Mailbox (%s)" "Mailbox" - "Vibrieren" - "Vibrieren" - "Ton" + + "Erweiterte Einstellungen" "Visuelle Mailbox" "Zusätzliche Sicherung und mehr Speicher" - " ""Dies ist eine Funktion im Versuchsstadium"", die gerade getestet wird. Hiermit werden möglicherweise Mailboxnachrichten von deinem Mailbox-Server gelöscht. Es wird nicht garantiert, dass diese Funktion auch in Zukunft unterstützt wird. Wir würden uns aber sehr über Feedback dazu freuen." "PIN festlegen" "PIN ändern" "Die visuelle Mailbox muss aktiviert sein, um die PIN zu ändern" diff --git a/java/com/android/voicemail/impl/res/values-el/strings.xml b/java/com/android/voicemail/impl/res/values-el/strings.xml index a416936b97437cc3f937f2231ebe09b0dea1b11b..5456c48756d1338d076abb3d96425db96c783251 100644 --- a/java/com/android/voicemail/impl/res/values-el/strings.xml +++ b/java/com/android/voicemail/impl/res/values-el/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Αυτόματος τηλεφωνητής (%s)" "Αυτόματος τηλεφωνητής" - "Δόνηση" - "Δόνηση" - "Ήχος" + + "Σύνθετες ρυθμίσεις" "Οπτικός αυτόματος τηλεφωνητής" "Επιπλέον αντίγραφα ασφ. και αποθήκευση" - " ""Αυτή είναι μια πειραματική λειτουργία"" που δοκιμάζουμε προς το παρόν. Ενδέχεται να έχει ως αποτέλεσμα τη διαγραφή φωνητικών μηνυμάτων από τον διακομιστή αυτόματου τηλεφωνητή σας. Δεν παρέχονται εγγυήσεις για την υποστήριξη αυτής της λειτουργίας μελλοντικά. Ωστόσο, θα εκτιμούσαμε τα σχόλιά σας για τη λειτουργία αυτή." "Ορισμός PIN" "Αλλαγή κωδικού PIN" "Για αλλαγή του PIN, ενεργοποιήστε τον οπτικό αυτόματο τηλεφωνητή" diff --git a/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml b/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml index 9b6484b456b212fa66b66d351dbb316b308a157d..dba1f1624439dbbbce7d0209fe01facea2f5c73f 100644 --- a/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml +++ b/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Voicemail (%s)" "Voicemail" - "Vibrate" - "Vibrate" - "Sound" + + "Advanced settings" "Visual voicemail" "Extra backup and storage" - " ""This is an experimental feature"" that we are currently testing. This will potentially delete voicemail from your voicemail server. There are no guarantees that this feature will be supported in the future. We would love feedback on the feature though." "Set PIN" "Change PIN" "Visual voicemail must be enabled to change PIN" diff --git a/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml b/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml index 9b6484b456b212fa66b66d351dbb316b308a157d..dba1f1624439dbbbce7d0209fe01facea2f5c73f 100644 --- a/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml +++ b/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Voicemail (%s)" "Voicemail" - "Vibrate" - "Vibrate" - "Sound" + + "Advanced settings" "Visual voicemail" "Extra backup and storage" - " ""This is an experimental feature"" that we are currently testing. This will potentially delete voicemail from your voicemail server. There are no guarantees that this feature will be supported in the future. We would love feedback on the feature though." "Set PIN" "Change PIN" "Visual voicemail must be enabled to change PIN" diff --git a/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml b/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml index 9b6484b456b212fa66b66d351dbb316b308a157d..dba1f1624439dbbbce7d0209fe01facea2f5c73f 100644 --- a/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml +++ b/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Voicemail (%s)" "Voicemail" - "Vibrate" - "Vibrate" - "Sound" + + "Advanced settings" "Visual voicemail" "Extra backup and storage" - " ""This is an experimental feature"" that we are currently testing. This will potentially delete voicemail from your voicemail server. There are no guarantees that this feature will be supported in the future. We would love feedback on the feature though." "Set PIN" "Change PIN" "Visual voicemail must be enabled to change PIN" diff --git a/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml b/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml index 6ae227a81262988630da9a06d2c8325de2d83532..86cb7e934d77a169f6ba8a077baba7c8667610c9 100644 --- a/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml +++ b/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Buzón de voz (%s)" "Buzón de voz" - "Vibrar" - "Vibrar" - "Sonido" + + "Configuración avanzada" "Buzón de voz visual" "Copia de seguridad y almacenamiento adicional" - " ""Esta es una función experimental"" que estamos probando. Es posible que se borren los mensajes de voz del servidor correspondiente. No podemos garantizar la compatibilidad de la función en el futuro. Sin embargo, nos encantaría que nos hicieras comentarios acerca de ella." "Establecer PIN" "Cambiar PIN" "El buzón de voz visual se debe activar para cambiar el PIN" diff --git a/java/com/android/voicemail/impl/res/values-es/strings.xml b/java/com/android/voicemail/impl/res/values-es/strings.xml index bab4e0326bb69050ab5a980c7b2e48ebe3d45161..29863d177fb83622156cde2474774b21def25844 100644 --- a/java/com/android/voicemail/impl/res/values-es/strings.xml +++ b/java/com/android/voicemail/impl/res/values-es/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Buzón de voz (%s)" "Buzón de voz" - "Vibración" - "Vibrar" - "Sonido" + + "Configuración avanzada" "Buzón de voz visual" "Copias de seguridad y almacenamiento extra" - " ""Se trata de una función experimental"" que se encuentra actualmente en fase de prueba y que podría servir para eliminar los mensajes de tu servidor de buzón de voz. Aunque no garantizamos que esta función se siga admitiendo en el futuro, nos encantaría conocer tu opinión." "Establecer PIN" "Cambiar PIN" "Para poder cambiar el PIN, el buzón de voz visual debe estar habilitado" diff --git a/java/com/android/voicemail/impl/res/values-et/strings.xml b/java/com/android/voicemail/impl/res/values-et/strings.xml index 02f13145d23ae349757c0765764189df15f31b99..6fcf23392ef2a117ac9a08cca628d10d0d8312c7 100644 --- a/java/com/android/voicemail/impl/res/values-et/strings.xml +++ b/java/com/android/voicemail/impl/res/values-et/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Kõnepost (%s)" "Kõnepost" - "Vibreerimine" - "Vibreerimine" - "Heli" + + "Täpsemad seaded" "Visuaalne kõnepost" "Lisavarundus ja -salvestusruum" - " ""See on katseline funktsioon"", mida praegu testime. See võib teie kõnepostisõnumid kõnepostiserverist kustutada. Me ei garanteeri, et seda funktsiooni tulevikus toetatakse. Soovime selle kohta siiski tagasisidet saada." "PIN-koodi määramine" "PIN-koodi muutmine" "PIN-koodi muutmiseks peab olema lubatud visuaalne kõnepost" diff --git a/java/com/android/voicemail/impl/res/values-eu/strings.xml b/java/com/android/voicemail/impl/res/values-eu/strings.xml index 89afb830cd928faf56c3976b1a5d14cb41f0a524..293dd1c45023f90ea36b4ef47abf09db0e0b155d 100644 --- a/java/com/android/voicemail/impl/res/values-eu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-eu/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Erantzungailua (%s)" "Erantzungailua" - "Dardara" - "Dardara" - "Soinua" + + "Ezarpen aurreratuak" "Erantzungailu bisuala" "Babeskopiak eta edukia gordetzeko tokia" - " Oraindik probatzen ari garen ""eginbide esperimentala da hau"". Agian erantzungailuaren zerbitzarian gordetako mezuak ezabatuko dira. Ez dugu bermatzen egibide hau etorkizunean erabiltzeko aukera emango dugunik. Halere, bihotzez eskertuko genizuke eginbideari buruzko iritzia." "Ezarri PIN kodea" "Aldatu PIN kodea" "Ikusizko erantzungailuak gaituta egon behar du PIN kodea aldatu ahal izateko" diff --git a/java/com/android/voicemail/impl/res/values-fa/strings.xml b/java/com/android/voicemail/impl/res/values-fa/strings.xml index 3db711b346ca9a33e5c4d0775e1beaeff0ea453c..cc04d98f24e5c88d4f9fe3f40ffe11ab033f43e9 100644 --- a/java/com/android/voicemail/impl/res/values-fa/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fa/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "پست صوتی (%s)" "پست صوتی" - "لرزش" - "لرزش" - "صدا" + + "تنظیمات پیشرفته" "پست صوتی تصویری" "پشتیبان‌گیری و فضای ذخیره‌سازی اضافی" - " ""این یک قابلیت آزمایشی است"" که درحال آزمایش آن هستیم. این قابلیت به‌طور بالقوه پست‌های صوتی را از سرور پست صوتی شما حذف خواهد کرد. ضمانتی برای پشتیبانی از این قابلیت در آینده وجود ندارد. با این حال مشتاقیم درباره آن بازخورد دریافت کنیم." "تنظیم پین" "تغییر پین" "برای تغییر پین، پست صوتی تصویری باید فعال شود" diff --git a/java/com/android/voicemail/impl/res/values-fi/strings.xml b/java/com/android/voicemail/impl/res/values-fi/strings.xml index 36f5fff5d4d3f34e78abacfcdb3975771711ae65..0e1cda523ee59238729453686a2d37591c0a44ce 100644 --- a/java/com/android/voicemail/impl/res/values-fi/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fi/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Vastaaja (%s)" "Vastaaja" - "Värinä" - "Värinä" - "Ääni" + + "Lisäasetukset" "Visuaalinen vastaaja" "Lisävarmuuskopiointi ja ‑tallennustila" - " ""Tämä on kokeellinen ominaisuus"", jota testaamme parhaillaan. Vastaajaviestejä saatetaan poistaa vastaajapalvelimelta. Ominaisuuden tukemista tulevaisuudessa ei taata. Kuulemme kuitenkin mielellämme mielipiteesi ominaisuudesta." "Aseta PIN-koodi" "Vaihda PIN-koodi" "Ota visuaalinen puhelinvastaaja käyttöön, jotta voit vaihtaa PIN-koodin." diff --git a/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml b/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml index 2c9a11a93e383df3f7c7347d22da0fffe8a5a139..f570fa415c3b6cc19b294e3e7944c8d54885a8f9 100644 --- a/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Messagerie vocale (%s)" "Messagerie vocale" - "Vibreur" - "Vibreur" - "Son" + + "Paramètres avancés" "Messagerie vocale visuelle" "Espace suppl. de sauvegarde et stockage" - " ""Fonction expérimentale"" en cours de test." "Définir un NIP" "Modifier le NIP" "La messagerie vocale visuelle doit être activée pour que vous puissiez modifier votre NIP" diff --git a/java/com/android/voicemail/impl/res/values-fr/strings.xml b/java/com/android/voicemail/impl/res/values-fr/strings.xml index 391671c2e0cf35386b33c8d7a78f1c684626e212..323decf84d37e8f353f6f36a45b4c8571bdf8358 100644 --- a/java/com/android/voicemail/impl/res/values-fr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fr/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Messagerie vocale (%s)" "Messagerie vocale" - "Vibreur" - "Vibreur" - "Sonnerie" + + "Paramètres avancés" "Messagerie vocale visuelle" "Espace suppl. de sauvegarde et stockage" - " ""Il s\'agit d\'une fonctionnalité expérimentale"" en cours de test. Des messages risquent d\'être supprimés de votre serveur de messagerie vocale. Nous ne pouvons pas garantir le maintien de cette fonctionnalité. Toutefois, n\'hésitez pas à nous faire part de vos commentaires." "Définir le code secret" "Modifier le code secret" "Pour que vous puissiez modifier le code secret, la messagerie vocale visuelle doit être activée" diff --git a/java/com/android/voicemail/impl/res/values-gl/strings.xml b/java/com/android/voicemail/impl/res/values-gl/strings.xml index 70b949e6c792e561e6abef773973eee191649ea7..b6ff512d24a62764c335cea3f405e77c4ff9c97a 100644 --- a/java/com/android/voicemail/impl/res/values-gl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-gl/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Correo de voz (%s)" "Correo de voz" - "Vibración" - "Vibración" - "Son" + + "Configuración avanzada" "Correo de voz visual" "Copia de seguranza e almacenamento extra" - " ""Esta función está en modo de proba"", e é posible que elimine correos de voz do teu servidor de correo de voz. Non podemos garantir a súa continuidade no futuro. De todos modos, encantaríanos que nos deses a túa opinión." "Establecer PIN" "Cambiar PIN" "Para poder cambiar o PIN, o correo de voz visual ten que estar activado" diff --git a/java/com/android/voicemail/impl/res/values-gu/strings.xml b/java/com/android/voicemail/impl/res/values-gu/strings.xml index f9187a7d39eefc8ef3b8ca918d6c63af60d8c4cd..684bd40fcb84fd0326d0f806e6806f4e8446fc8d 100644 --- a/java/com/android/voicemail/impl/res/values-gu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-gu/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "વૉઇસમેઇલ (%s)" "વૉઇસમેઇલ" - "વાઇબ્રેટ" - "વાઇબ્રેટ" - "ધ્વનિ" + + "વિગતવાર સેટિંગ્સ" "વિઝ્યુઅલ વૉઇસમેઇલ" "અતિરિક્ત બેકઅપ અને સ્ટોરેજ" - " ""આ એક પ્રાયોગિક સુવિધા છે"" અમે હાલમાં પરીક્ષણ કરી રહ્યાં છીએ. આ તમારા વૉઇસમેઇલ સર્વરમાંથી સંભવિત રૂપે વૉઇસમેઇલ કાઢી નાખશે. ભવિષ્યમાં આ સુવિધાનું સમર્થન કરવાની કોઇ બાંંયધરી નથી. જોકે અમને આ સુવિધા પર પ્રતિસાદ ગમશે." "PIN સેટ કરો" "PIN બદલો" "PIN બદલવા માટે વિઝ્યુઅલ વૉઇસમેઇલ સક્ષમ હોય તે આવશ્યક છે" diff --git a/java/com/android/voicemail/impl/res/values-hi/strings.xml b/java/com/android/voicemail/impl/res/values-hi/strings.xml index 488fba2a98e3b64a0360ffd701b332e37ab5645a..3cb394f4656455e821017e7dc0f22dbc42edf6af 100644 --- a/java/com/android/voicemail/impl/res/values-hi/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hi/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "वॉइसमेल (%s)" "वॉइसमेल" - "कंपन" - "कंपन" - "ध्वनि" + + "उन्नत सेटिंग" "विज़ुअल वॉइसमेल" "अतिरिक्त बैकअप और जगह" - " ""यह सुविधा एक तरह का प्रयोग है"" जिसका हम अभी परीक्षण कर रहे हैं. हो सकता है कि यह आपके वॉइसमेल सर्वर से वॉइसमेल हटा दे. भविष्य में यह सुविधा दी जाएगी या नहीं इसकी कोई गारंटी नहीं है. फिर भी सुविधा पर आपका फ़ीडबैक हमें अच्छा लगेगा." "पिन सेट करें" "पिन बदलें" "पिन बदलने के लिए विज़ुअल वॉइसमेल ज़रूर सक्षम होना चाहिए" diff --git a/java/com/android/voicemail/impl/res/values-hr/strings.xml b/java/com/android/voicemail/impl/res/values-hr/strings.xml index 7d66956536beab434db9f4837ca2a70308481488..6eb0bbc40ac1b63c832e4916aa9a9562ab990c84 100644 --- a/java/com/android/voicemail/impl/res/values-hr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hr/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Govorna pošta (%s)" "Govorna pošta" - "Vibriranje" - "Vibriranje" - "Zvuk" + + "Napredne postavke" "Vizualna govorna pošta" "Dodatno sigurnosno kopiranje i pohrana" - " ""Ovo je eksperimentalna značajka"" koju trenutačno testiramo. To će možda izbrisati poruke govorne pošte s vašeg poslužitelja govorne pošte. Nije sigurno da ćemo ovu značajku podržati u budućnosti. Međutim, voljeli bismo dobiti povratne informacije o njoj." "Postavljanje PIN-a" "Promjena PIN-a" "Za promjenu PIN-a potrebno je omogućiti vizualnu govornu poštu" diff --git a/java/com/android/voicemail/impl/res/values-hu/strings.xml b/java/com/android/voicemail/impl/res/values-hu/strings.xml index fae3ef4c7a3d7b1a78c7b0d4ef5b97c3a9448f89..b764122754d2e46892e11eebc6098c72baf066a3 100644 --- a/java/com/android/voicemail/impl/res/values-hu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hu/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Hangposta (%s)" "Hangposta" - "Rezgés" - "Rezgés" - "Hang" + + "Speciális beállítások" "Vizuális hangpostaüzenet" "Extra tárhely és biztonsági mentés" - " ""Ez egy kísérleti funkció"", amelyet jelenleg tesztelünk. Előfordulhat, hogy letörli az Ön hangüzeneteit a hangpostaszerverről. Nem garantáljuk, hogy a funkció a jövőben is megmarad, de nagy örömmel vennénk, ha megírná róla a véleményét." "PIN-kód beállítása" "PIN-kód módosítása" "A PIN-kód módosításához engedélyezni kell a vizuális hangpostát." diff --git a/java/com/android/voicemail/impl/res/values-hy/strings.xml b/java/com/android/voicemail/impl/res/values-hy/strings.xml index e4126f8772980d2f2010b4ac87461d5952c17c64..23544bad8de393cd5a35cec302f715055f4a9b1a 100644 --- a/java/com/android/voicemail/impl/res/values-hy/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hy/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ձայնային փոստ (%s)" "Ձայնային փոստ" - "Թրթռոց" - "Թրթռոց" - "Ձայն" + + "Ընդլայնված կարգավորումներ" "Տեսողական ձայնային փոստ" "Լրացուցիչ տարածք և պահուստավորում" - " ""Սա փորձնական գործառույթ է,"" որը գտնվում է փորձարկման փուլում: Այս ընթացքում ձայնային հաղորդագրությունները ձեր ձայնային փոստի սերվերից կարող են ջնջվել: Ոչ մի երաշխիք չկա, որ այն հետագայում կաջակցվի: Այդուհանդերձ, կցանկանայինք ձեր կարծիքն իմանալ այս գործառույթի մասին:" "Սահմանեք PIN կոդ" "Փոխեք PIN կոդը" "PIN կոդը փոխելու համար տեսողական ձայնային փոստը պետք է միացված լինի" diff --git a/java/com/android/voicemail/impl/res/values-in/strings.xml b/java/com/android/voicemail/impl/res/values-in/strings.xml index d47bd9b9bd2c2c3344348f6c0c19f25b9fe9f2af..76ad479445703f68f099dad2798627491fb18b41 100644 --- a/java/com/android/voicemail/impl/res/values-in/strings.xml +++ b/java/com/android/voicemail/impl/res/values-in/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Pesan Suara (%s)" "Pesan Suara" - "Getar" - "Getar" - "Suara" + + "Setelan Lanjutan" "Pesan Suara Visual" "Penyimpanan dan backup ekstra" - " ""Ini adalah fitur eksperimental"" yang sedang kami uji. Fitur ini berpotensi menghapus pesan suara dari server pesan suara Anda. Tidak ada jaminan bahwa fitur ini akan didukung di masa mendatang. Kami akan menerima masukan terkait fitur ini dengan senang hati." "Setel PIN" "Ubah PIN" "Pesan suara visual harus diaktifkan untuk mengubah PIN" diff --git a/java/com/android/voicemail/impl/res/values-is/strings.xml b/java/com/android/voicemail/impl/res/values-is/strings.xml index c2019a3f5d528bf521bbbeb91d18971681f9d09c..26ee45a75c5fbae66a017a2a0e14b7932c136dc4 100644 --- a/java/com/android/voicemail/impl/res/values-is/strings.xml +++ b/java/com/android/voicemail/impl/res/values-is/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Talhólf (%s)" "Talhólf" - "Titringur" - "Titringur" - "Hljóð" + + "Ítarlegar stillingar" "Myndrænt talhólf" "Viðbótaröryggisafritun og samstilling" - " ""Þessi eiginleiki er í tilraunaútgáfu"" sem við erum að prófa að svo stöddu. Þetta mun mögulega eyða talhólfsskilaboðum af vefþjóni talhólfsins. Engin trygging er fyrir því að þessi eiginleiki verði studdur í framtíðinni. Við kunnum virkilega að meta allar ábendingar varðandi þennan eiginleika." "Stilla PIN-númer" "Breyta PIN-númeri" "Kveikt þarf að vera á myndrænu talhólfi til að breyta PIN-númeri" diff --git a/java/com/android/voicemail/impl/res/values-it/strings.xml b/java/com/android/voicemail/impl/res/values-it/strings.xml index 3aeaca901651756bad63aa3bf66ba1137d43a05d..3f28d45634a887404b3e5ab26188f383f2986abf 100644 --- a/java/com/android/voicemail/impl/res/values-it/strings.xml +++ b/java/com/android/voicemail/impl/res/values-it/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Segreteria (%s)" "Segreteria" - "Vibrazione" - "Vibrazione" - "Suono" + + "Impostazioni avanzate" "Leggi la segreteria" "Archiviazione supplementare e backup" - " ""Questa è una funzionalità sperimentale"" che si trova al momento in fase di test. È possibile che i messaggi vocali vengano eliminati dal server della segreteria. Non ci sono garanzie che la funzionalità continui a essere supportata in futuro, ma ci piacerebbe ricevere il tuo feedback." "Imposta PIN" "Cambia PIN" "La lettura delle segreteria deve essere attivata per cambiare il PIN" diff --git a/java/com/android/voicemail/impl/res/values-iw/strings.xml b/java/com/android/voicemail/impl/res/values-iw/strings.xml index 98d31bc59bb19bbbda181bfb4ed423dc1525431a..f808e9853a0f5538f45d52d1a17d725d9d3fcc4a 100644 --- a/java/com/android/voicemail/impl/res/values-iw/strings.xml +++ b/java/com/android/voicemail/impl/res/values-iw/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "דואר קולי (%s)" "דואר קולי" - "רטט" - "רטט" - "צליל" + + "הגדרות מתקדמות" "דואר קולי ויזואלי" "גיבוי ופינוי מקום" - " ""זוהי תכונה ניסיונית"" שאנחנו בודקים כרגע. היא עלולה למחוק הודעות קוליות מתא הדואר הקולי שלך בשרת. אנחנו לא מתחייבים שהתכונה תהיה זמינה בעתיד, אך נשמח לקבל עליה משוב." "הגדרת קוד גישה" "שינוי קוד הגישה" "צריך להפעיל את הדואר הקולי הוויזואלי כדי לשנות את קוד הגישה" diff --git a/java/com/android/voicemail/impl/res/values-ja/strings.xml b/java/com/android/voicemail/impl/res/values-ja/strings.xml index 90bce09fb531d148de6eedbe6606621218483c93..75dcd5e080715e929eb22c3f3c437dbfc16599f4 100644 --- a/java/com/android/voicemail/impl/res/values-ja/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ja/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ボイスメール(%s)" "ボイスメール" - "バイブレーション" - "バイブレーション" - "通知音" + + "詳細設定" "ビジュアル ボイスメール" "追加のバックアップと保存容量" - " ""これは現在テスト中の試験運用機能""で、ボイスメール サーバーからボイスメールを削除することができます。今後この機能が正式にサポートされる保証はありませんが、フィードバックをお寄せいただければ幸いです。" "PIN の設定" "PIN の変更" "PIN を変更するには、ビジュアル ボイスメールを有効にする必要があります" diff --git a/java/com/android/voicemail/impl/res/values-ka/strings.xml b/java/com/android/voicemail/impl/res/values-ka/strings.xml index 4e141328788b275ba786955a187a3480cb23de60..8c46747ff11b4b0bbd9916f4c28d3660c9ce123f 100644 --- a/java/com/android/voicemail/impl/res/values-ka/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ka/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ხმოვანი ფოსტა (%s)" "ხმოვანი ფოსტა" - "ვიბრაცია" - "ვიბრაცია" - "ხმა" + + "გაფართოებული პარამეტრები" "ვიზუალური ხმოვანი ფოსტა" "დამატებითი სარეზ. ასლები და მეხსიერება" - " ""ეს არის ექსპერიმენტული ფუნქცია, რომელსაც"" ამჟამად ტესტირებას ვუტარებთ. სავარაუდოდ, ეს წაშლის ხმოვან შეტყობინებებს თქვენი ხმოვანი ფოსტის სერვერიდან. გარანტია, რომ ეს ფუნქცია მომავალში მხარდაჭერილი იქნება, არ არსებობს. თუმცა ამ ფუნქციის შესახებ გამოხმაურებას ინტერესით გავეცნობოდით." "PIN-კოდის დაყენება" "PIN-კოდის შეცვლა" "PIN-კოდის შესაცვლელად ჩართული უნდა იყოს ვიზუალური ხმოვანი ფოსტა" diff --git a/java/com/android/voicemail/impl/res/values-kk/strings.xml b/java/com/android/voicemail/impl/res/values-kk/strings.xml index 36ba090eae84d403742b568855cfe8f0ad6e2532..1badcfd9248626edf99ceb3d015dc16250728f3a 100644 --- a/java/com/android/voicemail/impl/res/values-kk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-kk/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Дауыстық хабар (%s)" "Дауыстық хабар" - "Діріл" - "Діріл" - "Дыбыс" + + "Қосымша параметрлер" "Визуалды дауыстық пошта" "Қосымша сақтық көшірме жасау және сақтау" - " ""Бұл — қазір тексеріліп жатқан, тәжірибелік мүмкіндік"". Бұл дауыстық хабарларды дауыстық хабар серверінен өшіруі мүмкін. Осы мүмкіндікке алдағы уақытта қолдау көрсетілетініне ешқандай кепілдік жоқ. Сонда да осы мүмкіндікке қатысты пікір алғымыз келеді." "PIN кодын тағайындау" "PIN кодын өзгерту" "PIN кодын өзгерту үшін визуалды дауыс хабарын қосу қажет" diff --git a/java/com/android/voicemail/impl/res/values-km/strings.xml b/java/com/android/voicemail/impl/res/values-km/strings.xml index f97ff3e5e60d2b219f535fc560fc96dab3fc8eb2..35fdb490a326ecbc4b949b7319fc744d35441693 100644 --- a/java/com/android/voicemail/impl/res/values-km/strings.xml +++ b/java/com/android/voicemail/impl/res/values-km/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "សារ​ជា​សំឡេង (%s)" "សារ​ជា​សំឡេង" - "ញ័រ" - "ញ័រ" - "សំឡេង" + + "ការ​កំណត់​កម្រិត​ខ្ពស់" "សារជាសំឡេងអាចមើលឃើញ" "ទំហំ​ផ្ទុក និង​ការ​បម្រុងទុក​បន្ថែម" - " ""នេះ​​គឺ​ជា​មុខងារ​សាកល្បង"" បច្ចុប្បន្ន យើង​កំពុង​ធ្វើ​ការ​សាកល្បង។ វា​អាច​នឹង​លុប​សារ​ជា​សំឡេង​ពី​ម៉ាស៊ីន​មេ​សារ​ជា​សំឡេង​របស់​អ្នក។ មិន​មាន​ការ​ធានា​ធ្វើ​ឲ្យ​មុខងារ​នេះ​ដំណើរការ​នៅ​ថ្ងៃ​ក្រោយ​ទេ។ យើង​ចង់​ដឹង​មតិ​ស្ថាបនា​អំពី​មុខងារនេះ​ផង​ដែរ។" "កំណត់​កូដ PIN" "ផ្លាស់ប្ដូរ​កូដ PIN" "សារ​​ជា​សំឡេង​ដែល​មើល​ឃើញ​ត្រូវតែ​បើកដំណើរការ ដើម្បី​ផ្លាស់ប្ដូរ PIN" diff --git a/java/com/android/voicemail/impl/res/values-kn/strings.xml b/java/com/android/voicemail/impl/res/values-kn/strings.xml index 6f8e21f8886eb62318982ee2a1eced5fb9bc37cf..5ab3a2e759b5a0d424d7c5950b5f6d275a663101 100644 --- a/java/com/android/voicemail/impl/res/values-kn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-kn/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ಧ್ವನಿಮೇಲ್ (%s)" "ಧ್ವನಿಮೇಲ್" - "ವೈಬ್ರೇಟ್‌" - "ವೈಬ್ರೇಟ್‌" - "ಶಬ್ದ" + + "ಸುಧಾರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ದೃಶ್ಯ ಧ್ವನಿಮೇಲ್" "ಹೆಚ್ಚುವರಿ ಬ್ಯಾಕಪ್ ಮತ್ತು ಸಂಗ್ರಹಣೆ" - " ""ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ""ನಾವು ಪ್ರಸ್ತುತ ಪರೀಕ್ಷಿಸುತ್ತಿದ್ದೇವೆ. ಇದು ನಿಮ್ಮ ಧ್ವನಿಮೇಲ್ ಸರ್ವರ್‌ನಿಂದ ಧ್ವನಿಮೇಲ್‌ಗಳನ್ನು ಸಂಭಾವ್ಯವಾಗಿ ಅಳಿಸುತ್ತದೆ. ಭವಿಷ್ಯದಲ್ಲಿ ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬೆಂಬಲಿಸುವ ಯಾವುದೇ ಖಾತ್ರಿ ಇಲ್ಲ. ಆದರೂ ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಗೆ ಸ್ವಾಗತ." "ಪಿನ್ ಹೊಂದಿಸಿ" "ಪಿನ್‌ ಬದಲಾಯಿಸಿ" "ಪಿನ್ ಬದಲಾಯಿಸಲು ದೃಶ್ಯ ಧ್ವನಿಮೇಲ್ ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು" diff --git a/java/com/android/voicemail/impl/res/values-ko/strings.xml b/java/com/android/voicemail/impl/res/values-ko/strings.xml index f18d1d711467cb8180c63487aeda106a21ba13b7..98195e04f81591c12b6c65f05c98920ae2bcf622 100644 --- a/java/com/android/voicemail/impl/res/values-ko/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ko/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "음성사서함(%s)" "음성사서함" - "진동" - "진동" - "소리" + + "고급 설정" "시각적 음성사서함" "추가 백업 및 저장용량" - " 현재 테스트 중인 ""실험적 기능입니다"". 이 기능으로 인해 음성사서함 서버에서 메시지가 삭제될 수도 있습니다. 또한 Google에서는 추후 이 기능이 지원된다고 보장할 수 없습니다. 하지만 이 기능에 관해 의견을 주시면 감사하겠습니다." "PIN 설정" "PIN 변경" "PIN을 변경하려면 시각적 음성사서함이 사용 설정되어 있어야 합니다." diff --git a/java/com/android/voicemail/impl/res/values-ky/strings.xml b/java/com/android/voicemail/impl/res/values-ky/strings.xml index f5219a91c2834048704b3278146a7407589d5cd8..5ba4ddeba3f582b4b242c593b38aa2cce1cde167 100644 --- a/java/com/android/voicemail/impl/res/values-ky/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ky/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Үн почтасы (%s)" "Үн почтасы" - "Дирилдөө" - "Дирилдөө" - "Үн" + + "Өркүндөтүлгөн жөндөөлөр" "Визуалдык үн почтасы" "Кошумча камдык көчүрмөнү сактоо жана сактагыч" - " ""Бул, сыноодон өтүп жаткан"" эксперименталдык функция. Үн каттарыңыз серверден өчүрүлүп калышы мүмкүн. Бул функциянын кийин да колдонулаарына кепилдик бере албайбыз бирок, ал жөнүндө пикириңизди билгибиз келет." "PIN код коюу" "PIN кодду өзгөртүү" "PIN кодду өзгөртүү үчүн визуладык үн почтасын иштетүү керек" diff --git a/java/com/android/voicemail/impl/res/values-lo/strings.xml b/java/com/android/voicemail/impl/res/values-lo/strings.xml index 212b12fd292f597384454de3f8fee61e269309eb..ef9cecc8d962804aa511eac3ee1b63e3f2ee278b 100644 --- a/java/com/android/voicemail/impl/res/values-lo/strings.xml +++ b/java/com/android/voicemail/impl/res/values-lo/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ຂໍ້​ຄວາມ​ສຽງ (%s)" "ຂໍ້ຄວາມສຽງ" - "ສັ່ນເຕືອນ" - "ສັ່ນເຕືອນ" - "ສຽງ" + + "ການຕັ້ງຄ່າຂັ້ນສູງ" "ຂໍ້​ຄວາມ​ສຽງສະເໝືອນ" "ການສຳຮອງ ແລະ ບ່ອນຈັດເກັບຂໍ້ມູນພິເສດ" - " ""ນີ້ເປັນຄຸນສົມບັດທີ່ຢູ່ໃນຂັ້ນຕອນທົດລອງຢູ່"" ພວກເຮົາກຳລັງທົດສອບ. ມັນອາດລຶບຂໍ້ຄວາມສຽງອອກຈາກເຊີບເວີຂໍ້ຄວາມສຽງຂອງທ່ານໄດ້. ຈະບໍ່ມີການຮັບປະກັນການຊ່ວຍເຫຼືອຄຸນສົມບັດນີ້ໃນອະນາຄົດ. ຢ່າງໃດກໍຕາມພວກເຮົາຢາກຟັງຄຳຄິດເຫັນທີ່ມີຕໍ່ຄຸນສົມບັດດັ່ງກ່າວຈາກທ່ານ." "ຕັ້ງລະຫັດ PIN" "​ປ່ຽນ​ລະຫັດ PIN" "ຈະຕ້ອງເປີດໃຊ້ຂໍ້ຄວາມສຽງສະເໝືອນເພື່ອປ່ຽນ PIN" diff --git a/java/com/android/voicemail/impl/res/values-lt/strings.xml b/java/com/android/voicemail/impl/res/values-lt/strings.xml index d4d9c4dc3ad5ff2cb80495d3b312755ff2fd64a8..31dba2e5f63485bbd620a15ce5fc25fa509c3fc1 100644 --- a/java/com/android/voicemail/impl/res/values-lt/strings.xml +++ b/java/com/android/voicemail/impl/res/values-lt/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Balso paštas (%s)" "Balso paštas" - "Vibruoti" - "Vibravimas" - "Garsas" + + "Išplėstiniai nustatymai" "Vaizdinis balso paštas" "Papild. saug. vt. ir ats. kop. kūr. f." - " ""Tai yra eksperimentinė funkcija"", kurią šiuo metu išbandome. Ją naudojant iš balso pašto serverio bus ištrinami balso pašto pranešimai. Negarantuojame, kad ateityje ši funkcija bus palaikoma, tačiau norėtume gauti atsiliepimų apie ją." "PIN kodo nustatymas" "PIN kodo keitimas" "Vaizdinis balso paštas turi būti įgalintas, kad būtų galima pakeisti PIN kodą" diff --git a/java/com/android/voicemail/impl/res/values-lv/strings.xml b/java/com/android/voicemail/impl/res/values-lv/strings.xml index 1f758c46735e73e5b7ab20a42164096c33b8c5d1..d8230d9ec637c516a9d1672e1f1efe87bc0b8589 100644 --- a/java/com/android/voicemail/impl/res/values-lv/strings.xml +++ b/java/com/android/voicemail/impl/res/values-lv/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Balss pasts (%s)" "Balss pasts" - "Vibrācija" - "Vibrācija" - "Signāls" + + "Papildu iestatījumi" "Vizuālais balss pasts" "Papildu dublēšana un krātuve" - " ""Šī ir eksperimentāla funkcija"", ko mēs pašlaik testējam. Pastāv iespēja, ka no jūsu balss pasta servera tiks izdzēsti balss pasta ziņojumi. Mēs negarantējam šīs funkcijas turpmāku atbalstu, tomēr priecāsimies saņemt atsauksmes par to." "PIN iestatīšana" "PIN mainīšana" "Lai varētu mainīt PIN, ir jābūt iespējotam vizuālajam balss pastam." diff --git a/java/com/android/voicemail/impl/res/values-mk/strings.xml b/java/com/android/voicemail/impl/res/values-mk/strings.xml index 39b8beefca4bf60c3e2623cf88beaec9f606c8bf..375b79a7ff6667f8907c6dc14efb4ac10c0916ce 100644 --- a/java/com/android/voicemail/impl/res/values-mk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-mk/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Говорна пошта (%s)" "Говорна пошта" - "Вибрации" - "Вибрации" - "Звук" + + "Напредни поставки" "Визуелна говорна пошта" "Дополнителен бекап и склад" - " ""Ова е експериментална функција"" што моментално ја тестираме. Постои можност да брише говорни пораки од вашиот сервер за говорна пошта. Нема гаранција дека функцијава ќе се поддржува во иднина. Сепак, многу би ни значеле повратните информации за функцијата." "Поставете PIN" "Променете PIN" "За променување на PIN-кодот, мора да се овозможи визуелна говорна пошта" diff --git a/java/com/android/voicemail/impl/res/values-ml/strings.xml b/java/com/android/voicemail/impl/res/values-ml/strings.xml index c30ebbcfe570d4f50c181ec37246b3fc4ff03d8e..d21d8bed92c3420a0419b3b6158b2d3ab9dbce0b 100644 --- a/java/com/android/voicemail/impl/res/values-ml/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ml/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "വോയ്‌സ്‌മെയിൽ (%s)" "വോയ്‌സ്‌മെയിൽ" - "വൈബ്രേറ്റുചെയ്യുക" - "വൈബ്രേറ്റുചെയ്യുക" - "ശബ്‌ദം" + + "വിപുലമായ ക്രമീകരണം" "വിഷ്വൽ വോയ്‌സ്‌മെയിൽ" "അധിക ബായ്‌ക്കപ്പും സ്‌റ്റോറേജും" - " ഇത് നിലവിൽ ഞങ്ങൾ പരീക്ഷിക്കുന്ന ""ഒരു പരീക്ഷണാത്മക ഫീച്ചറാണ്"". ഇത് നിങ്ങളുടെ വോയ്‌സ്‌മെയിൽ സെർവറിൽ നിന്ന് വോയ്‌സ്‌മെയിലുകൾ ഇല്ലാതാക്കാൻ സാധ്യതയുണ്ട്. ഈ ഫീച്ചർ ഭാവിയിൽ ഉപയോഗിക്കാനാവുമെന്ന് ഉറപ്പൊന്നുമില്ല. എങ്കിലും ഈ ഫീച്ചറിനെക്കുറിച്ചുള്ള ഫീഡ്‌ബാക്ക് അറിയാൻ ഞങ്ങൾ താൽപ്പര്യപ്പെടുന്നു." "പിൻ സജ്ജമാക്കുക" "പിൻ മാറ്റുക" "പിൻ മാറ്റുന്നതിന് വിഷ്വൽ വോയ്‌സ്‌മെയിൽ പ്രവർത്തനക്ഷമമാക്കേണ്ടതുണ്ട്" diff --git a/java/com/android/voicemail/impl/res/values-mn/strings.xml b/java/com/android/voicemail/impl/res/values-mn/strings.xml index a559d1900f2cf320d197b922f3ba9afed0df3173..56cffa9e0282c6acb829acf9ed804dc6749ed8af 100644 --- a/java/com/android/voicemail/impl/res/values-mn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-mn/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Дуут шуудан (%s)" "Дуут шуудан" - "Чичиргээ" - "Чичиргээ" - "Дуу" + + "Нарийвчилсан тохиргоо" "Уншиж болохуйц дуут шуудан" "Нэмэлт нөөцлөлт болон хадгалах сан" - " Энэ бол бидний одоо шалгаж буй ""туршилтын функц"". Энэ таны дуут шуудангийн серверээс дуут шуудангуудыг устгах магадлалтай. Цаашид энэ функцийг дэмжих баталгаа байхгүй. Гэхдээ энэ функцийн талаар санал хүсэлт илгээвэл талархах болно." "PIN тохируулах" "PIN өөрчлөх" "Харагдах дуут шуудан PIN-г өөрчлөх боломжтой байх ёстой" diff --git a/java/com/android/voicemail/impl/res/values-mr/strings.xml b/java/com/android/voicemail/impl/res/values-mr/strings.xml index 56e864b810b8c1749701696bf5742a0139d4fbd1..407909876bdbe4e5e0fd50e4390b558fc74a247e 100644 --- a/java/com/android/voicemail/impl/res/values-mr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-mr/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "व्हॉइसमेल (%s)" "व्हॉइसमेल" - "कंपन करा" - "कंपन करा" - "ध्वनी" + + "प्रगत सेटिंग्ज" "दृश्‍यमान व्हॉइसमेल" "अतिरिक्त बॅक अप आणि संचय" - " ""हे प्रायोगिक वैशिष्ट्य आहे"" आम्ही सध्‍या चाचणी घेत आहोत. हे आपल्या व्हॉइसमेल सर्व्हर मधून संभाव्यपणे व्हॉइसमेल हटवेल. भविष्‍यात या वैशिष्‍ट्यास समर्थन देण्याची हमी नाही. तरीही आम्ही वैशिष्‍ट्यावरील अभिप्राय घेऊ इच्छितो." "पिन सेट करा" "पिन बदला" "पिन बदलण्‍यासाठी व्हिज्युअल व्हॉइसमेल सक्षम करणे आवश्‍यक आहे" diff --git a/java/com/android/voicemail/impl/res/values-ms/strings.xml b/java/com/android/voicemail/impl/res/values-ms/strings.xml index ea9b38f082ba027de59b4b2ff60604fc15fe9f89..91fa3051ee5b3df9318d616e4b8edb90a5c8e482 100644 --- a/java/com/android/voicemail/impl/res/values-ms/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ms/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Mel suara (%s)" "Mel suara" - "Bergetar" - "Bergetar" - "Bunyi" + + "Tetapan Terperinci" "Mel Suara Visual" "Sandaran dan storan tambahan" - " ""Ini ialah ciri percubaan"" yang sedang kami uji. Ciri ini berupaya memadamkan mel suara daripada pelayan mel suara anda. Tiada jaminan bahawa ciri ini akan disokong pada masa hadapan. Namun begitu, kami berharap untuk menerima maklum balas tentang ciri ini." "Tetapkan PIN" "Tukar PIN" "Mel suara visual mesti didayakan untuk menukar PIN" diff --git a/java/com/android/voicemail/impl/res/values-my/strings.xml b/java/com/android/voicemail/impl/res/values-my/strings.xml index 6c789275a1288f0d61ddc1f2b7c42da2681386a3..8144c1f4934fde59732c562a00b543b495a310e7 100644 --- a/java/com/android/voicemail/impl/res/values-my/strings.xml +++ b/java/com/android/voicemail/impl/res/values-my/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "အသံမေးလ် (%s)" "အသံမေးလ်" - "တုန်ခါမှု" - "တုန်ခါမှု" - "အသံ" + + "အဆင့်မြင့် ဆက်တင်များ" "စာသားမှတ်တမ်းပါ အသံမေးလ်" "အပိုဆောင်း မိတ္တူနှင့် သိုလှောင်မှု" - " ဤသည်မှာ ""စမ်းသပ်ဆဲဝန်ဆောင်မှုတစ်ခု"" ဖြစ်ပါသည်။ ၎င်းက သင်၏အသံမေးလ်ဆာဗာမှ အသံမေးလ်များကို ဖျက်ပစ်နိုင်ပါသည်။ ဤဝန်ဆောင်မှုကို အနာဂတ်တွင် ဆက်လက်ရရှိနိုင်မည်ဟု အာမခံထားခြင်း မရှိသော်လည်း ၎င်းနှင့်ပတ်သက်သည့် အကြံပြုချက်များကို ရရှိလိုပါသည်။" "ပင်နံပါတ် သတ်မှတ်ပါ" "ပင်နံပါတ် ပြောင်းပါ" "ပင်နံပါတ်ပြောင်းရန် စာသားမှတ်တမ်းပါ အသံမေးလ်ကို ဖွင့်ထားရပါမည်" diff --git a/java/com/android/voicemail/impl/res/values-nb/strings.xml b/java/com/android/voicemail/impl/res/values-nb/strings.xml index 93e9e2a2cc89673e11cec16837f6dfcd07ad6676..b13be25c4e804b7d8da3bca6dad119d8d00349b4 100644 --- a/java/com/android/voicemail/impl/res/values-nb/strings.xml +++ b/java/com/android/voicemail/impl/res/values-nb/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Talepostkasse (%s)" "Talepost" - "Vibrering" - "Vibrering" - "Lyd" + + "Avanserte innstillinger" "Visuell talepostkasse" "Ekstra sikkerhetskopi og lagring" - " ""Denne funksjonen er fortsatt under utforskning"", og det kan føre til at noen av talepostmelingene dine slettes. Vi kan dessverre ikke love at denne funksjonen støttes i fremtiden, men vi vil gjerne høre om hva du mener om den." "Angi PIN-kode" "Endre PIN-koden" "Du må slå på visuell talepost for å endre PIN-koden" diff --git a/java/com/android/voicemail/impl/res/values-ne/strings.xml b/java/com/android/voicemail/impl/res/values-ne/strings.xml index d729c2323c4f9ef59e30a5c4ab8f7c1c0f8dc518..360164eb5860b3feefb304744da2ecd15b2c9105 100644 --- a/java/com/android/voicemail/impl/res/values-ne/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ne/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "भ्वाइस मेल (%s)" "भ्वाइस मेल" - "कम्पन" - "कम्पन" - "आवाज" + + "उन्नत सेटिङहरू" "भिजुअल भ्वाइस मेल" "अतिरिक्त ब्याकअप र भण्डारण" - " ""यो एउटा प्रयोगात्मक विशेषता हो"" हामी अहिले परीक्षण गर्दैछौं। यसले सम्भवत: तपाईंको भ्वाइस मेल सर्भरका भ्वाइस मेलहरूलाई मेट्ने छ। भविष्यमा यो विशेषतालाई समर्थन गरिने कुराको ग्यारेन्टी छैन। तथापि हामी यो विशेषताका सम्बन्धमा प्रतिक्रिया आऊन् भन्ने चाहन्छौं।" "PIN सेट गर्नुहोस्" "PIN परिवर्तन गर्नुहोस्" "PIN परिवर्तन गर्न अनिवार्य रूपले भिजुअल भ्वाइस मेललाई सक्षम पारिनुपर्छ" diff --git a/java/com/android/voicemail/impl/res/values-nl/strings.xml b/java/com/android/voicemail/impl/res/values-nl/strings.xml index 7ae9f4e0eb97b0e6b420790e78b016da3fa01eec..88fc0f63f9d4be89571e5ebaad833f5e05054d04 100644 --- a/java/com/android/voicemail/impl/res/values-nl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-nl/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Voicemail (%s)" "Voicemail" - "Trillen" - "Trillen" - "Geluid" + + "Geavanceerde instellingen" "Visuele voicemail" "Extra back-up en opslag" - " ""Dit is een experimentele functie"" die wordt getest. Mogelijk worden hierdoor voicemails van de voicemailserver verwijderd. Er is geen garantie dat we deze functie in de toekomst blijven ondersteunen. We zijn wel heel benieuwd naar jullie feedback over de functie." "Pincode instellen" "Pincode wijzigen" "Visuele voicemail moet zijn ingeschakeld om de pincode te wijzigen" diff --git a/java/com/android/voicemail/impl/res/values-no/strings.xml b/java/com/android/voicemail/impl/res/values-no/strings.xml index 93e9e2a2cc89673e11cec16837f6dfcd07ad6676..b13be25c4e804b7d8da3bca6dad119d8d00349b4 100644 --- a/java/com/android/voicemail/impl/res/values-no/strings.xml +++ b/java/com/android/voicemail/impl/res/values-no/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Talepostkasse (%s)" "Talepost" - "Vibrering" - "Vibrering" - "Lyd" + + "Avanserte innstillinger" "Visuell talepostkasse" "Ekstra sikkerhetskopi og lagring" - " ""Denne funksjonen er fortsatt under utforskning"", og det kan føre til at noen av talepostmelingene dine slettes. Vi kan dessverre ikke love at denne funksjonen støttes i fremtiden, men vi vil gjerne høre om hva du mener om den." "Angi PIN-kode" "Endre PIN-koden" "Du må slå på visuell talepost for å endre PIN-koden" diff --git a/java/com/android/voicemail/impl/res/values-pa/strings.xml b/java/com/android/voicemail/impl/res/values-pa/strings.xml index f3551cc6ee794e177000c67026417ab71c9838fa..b7711b9030f382bd91ed6f6da185e68d3e5dda77 100644 --- a/java/com/android/voicemail/impl/res/values-pa/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pa/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ਵੌਇਸਮੇਲ (%s)" "ਵੌਇਸਮੇਲ" - "ਵਾਈਬ੍ਰੇਟ ਕਰੋ" - "ਵਾਈਬ੍ਰੇਟ ਕਰੋ" - "ਧੁਨੀ" + + "ਉੱਨਤ ਸੈਟਿੰਗਾਂ" "ਦ੍ਰਿਸ਼ਟਾਂਤਕ ਵੌਇਸਮੇਲ" "ਵਾਧੂ ਬੈਕਅੱਪ ਅਤੇ ਸਟੋਰੇਜ" - " ""ਇਹ ਇੱਕ ਪ੍ਰਯੋਗਾਤਮਕ ਵਿਸ਼ੇਸ਼ਤਾ ਹੈ"" ਜਿਸਦੀ ਅਸੀਂ ਇਸ ਵੇਲੇ ਜਾਂਚ ਕਰ ਰਹੇ ਹਾਂ। ਇਹ ਸੰਭਾਵੀ ਤੌਰ \'ਤੇ ਤੁਹਾਡੇ ਵੌਇਸਮੇਲ ਸਰਵਰ ਤੋਂ ਵੌਇਸਮੇਲਾਂ ਨੂੰ ਮਿਟਾ ਦੇਵੇਗੀ। ਭਵਿੱਖ ਵਿੱਚ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦਾ ਸਮਰਥਨ ਕਰਨ ਦੀਆਂ ਕੋਈ ਗਾਰੰਟੀਆਂ ਨਹੀਂ ਹਨ। ਅਸੀਂ ਹਾਲਾਂਕਿ ਵਿਸ਼ੇਸ਼ਤਾ \'ਤੇ ਪ੍ਰਤੀਕਰਮ ਨੂੰ ਪਸੰਦ ਕਰਾਂਗੇ।" "PIN ਸੈੱਟ ਕਰੋ" "PIN ਬਦਲੋ" "ਦ੍ਰਿਸ਼ਟਾਂਤਕ ਵੌਇਸਮੇਲ ਨੂੰ PIN ਬਦਲਣ ਲਈ ਯੋਗ ਬਣਾਇਆ ਜਾਣਾ ਲਾਜ਼ਮੀ ਹੈ" diff --git a/java/com/android/voicemail/impl/res/values-pl/strings.xml b/java/com/android/voicemail/impl/res/values-pl/strings.xml index 83003df9765382c37f869c4220667b777c340b7a..d240f7dbc51cc44df4df62246588137474f87f7e 100644 --- a/java/com/android/voicemail/impl/res/values-pl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pl/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Poczta głosowa (%s)" "Poczta głosowa" - "Wibracje" - "Wibracje" - "Dźwięk" + + "Ustawienia zaawansowane" "Wizualna poczta głosowa" "Dodatkowe miejsce i kopia zapasowa" - " ""To jest funkcja eksperymentalna"", którą obecnie testujemy. Może ona usunąć wiadomości głosowe z Twojego serwera poczty głosowej. Nie gwarantujemy, że ta funkcja będzie w przyszłości obsługiwana. Chętnie jednak dowiemy się, co o niej sądzisz." "Ustaw kod PIN" "Zmień kod PIN" "Aby można było zmienić kod PIN, wizualna poczta głosowa musi być włączona" diff --git a/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml b/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml index a0eee43aec5423492b1b81c0696e9507d1ab62a1..501924a35c930ed97a57e391fdf8ad714cb03259 100644 --- a/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Correio de voz (%s)" "Correio de voz" - "Vibração" - "Vibração" - "Som" + + "Configurações avançadas" "Correio de voz visual" "Armazenamento extra e backup" - " ""Este é um recurso experimental"" que estamos testando. Talvez ele exclua os correios de voz do seu servidor. Não há garantias de suporte no futuro, mas gostaríamos de receber seu feedback." "Definir PIN" "Alterar PIN" "O correio de voz visual precisa ser ativado para alterar o PIN" diff --git a/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml b/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml index 2be877e233a04c836b8728263be0d01b8bc1e928..d443329bb509310645b8e0927bd4243f524529ae 100644 --- a/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Correio de voz (%s)" "Correio de voz" - "Vibrar" - "Vibrar" - "Som" + + "Definições avançadas" "Mensagem de correio de voz visual" "Cópia de segurança e armazenamento extra" - " ""É uma funcionalidade experimental"" que estamos a testar. Poderá eliminar mensagens de correio de voz do servidor de correio de voz. Não há garantias de suporte para esta funcionalidade. Gostaríamos de receber comentários sobre a mesma." "Definir PIN" "Alterar PIN" "A mensagem de correio de voz visual tem de estar ativada para poder alterar o PIN" diff --git a/java/com/android/voicemail/impl/res/values-pt/strings.xml b/java/com/android/voicemail/impl/res/values-pt/strings.xml index a0eee43aec5423492b1b81c0696e9507d1ab62a1..501924a35c930ed97a57e391fdf8ad714cb03259 100644 --- a/java/com/android/voicemail/impl/res/values-pt/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pt/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Correio de voz (%s)" "Correio de voz" - "Vibração" - "Vibração" - "Som" + + "Configurações avançadas" "Correio de voz visual" "Armazenamento extra e backup" - " ""Este é um recurso experimental"" que estamos testando. Talvez ele exclua os correios de voz do seu servidor. Não há garantias de suporte no futuro, mas gostaríamos de receber seu feedback." "Definir PIN" "Alterar PIN" "O correio de voz visual precisa ser ativado para alterar o PIN" diff --git a/java/com/android/voicemail/impl/res/values-ro/strings.xml b/java/com/android/voicemail/impl/res/values-ro/strings.xml index 1c98d5a20518a934acf340fe8f2e439294701692..44bfd0d81c7d1717f45ff9c91b6123ec4f1d8daf 100644 --- a/java/com/android/voicemail/impl/res/values-ro/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ro/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Mesagerie vocală (%s)" "Mesagerie vocală" - "Vibrații" - "Vibrații" - "Sunet" + + "Setări avansate" "Mesagerie vocală vizuală" "Backup și spațiu de stocare suplimentare" - " ""Aceasta este o funcție experimentală"" în curs de testare. E posibil ca mesajele vocale de pe serverul de mesagerie vocală să fie șterse. Nu se poate garanta acceptarea acestei funcții pe viitor, însă feedbackul dvs. e bine-venit." "Setați codul PIN" "Schimbați codul PIN" "Mesageria vocală vizuală trebuie activată pentru a schimba codul PIN." diff --git a/java/com/android/voicemail/impl/res/values-ru/strings.xml b/java/com/android/voicemail/impl/res/values-ru/strings.xml index f899f149efe60edb6402e969b69a4fc733168b7c..b0512f8423607e61144f7e24a0a8a29bff9448ae 100644 --- a/java/com/android/voicemail/impl/res/values-ru/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ru/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Голосовая почта (%s)" "Голосовая почта" - "Вибросигнал" - "Вибросигнал" - "Звук" + + "Расширенные настройки" "Визуальная голосовая почта" "Дополнительное место для хранения и резервного копирования" - " ""Это экспериментальная функция"", которая сейчас проходит тестирование. Возможно, ваши голосовые сообщения будут удалены с вашего сервера. Поддержка этой функции в дальнейшем не гарантируется. Мы бы хотели узнать ваше мнение о ней." "Установка PIN-кода" "Изменение PIN-кода" "Чтобы изменить PIN-код, включите визуальную голосовую почту" diff --git a/java/com/android/voicemail/impl/res/values-si/strings.xml b/java/com/android/voicemail/impl/res/values-si/strings.xml index b5dc7826c77b387840297bd54db52e294c173fd9..ff16e6173d0ff66a22199d4ed33606e58fcc1a41 100644 --- a/java/com/android/voicemail/impl/res/values-si/strings.xml +++ b/java/com/android/voicemail/impl/res/values-si/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "හඬ තැපෑල (%s)" "හඬ තැපෑල" - "කම්පනය" - "කම්පනය කරන්න" - "හඬ" + + "උසස් සැකසීම්" "දෘශ්‍ය හඬ තැපෑල" "අතිරේක උපස්ථය සහ ගබඩාව" - " ""මෙය අත්හදා බැලීමේ විශේෂාංගයකි"" අපි දැන් පරීක්ෂා කරමින් සිටිමු. මෙය විභව්‍යව හඬ තැපැල් ඔබේ සේවාදායකයෙන් මකනු ඇත. මෙම විශේෂාංගය අනාගතයේදී සහාය දැක්වීම ගැන ඇපවීම් නැත. එසේ වුවත් අපි විශේෂාංගය ගැන ප්‍රතිපෝෂණවලට ආදරය කරන්නෙමු." "PIN අංකය සකසන්න" "PIN අංකය වෙනස් කරන්න" "PIN අංකය වෙනස් කිරීමට දෘශ්‍ය හඬ තැපෑල සබල කළ යුතුය" diff --git a/java/com/android/voicemail/impl/res/values-sk/strings.xml b/java/com/android/voicemail/impl/res/values-sk/strings.xml index 5a81a1bd457ff259cc85a995bcb07cd97021b687..a824ca83ff949874d38c715b53e6100aa3515ac6 100644 --- a/java/com/android/voicemail/impl/res/values-sk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sk/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Hlasová schránka %s" "Hlasová schránka" - "Vibrovať" - "Vibrovať" - "Zvuk" + + "Rozšírené nastavenia" "Vizuálna hlasová schránka" "Ďalšie zálohovanie a úložisko" - " ""Toto je experimentálna funkcia"", ktorú práve testujeme. Táto funkcia vám môže odstrániť hlasové správy zo servera hlasovej schránky. Nemôžeme zaručiť, že bude podporovaná aj v budúcnosti, no budeme vám vďační za poskytnutie spätnej väzby." "Nastavenie kódu PIN" "Zmena kódu PIN" "PIN možno zmeniť až po povolení vizuálnej hlasovej schránky" diff --git a/java/com/android/voicemail/impl/res/values-sl/strings.xml b/java/com/android/voicemail/impl/res/values-sl/strings.xml index ce0f40ec80948b49f2192451b305f4a02d73eaec..6ad9569e7e6534ab77cb040824e34e3e1485860c 100644 --- a/java/com/android/voicemail/impl/res/values-sl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sl/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Sporočilo v odzivniku (%s)" "Sporočilo v odzivniku" - "Vibriranje" - "Vibriranje" - "Zvok" + + "Dodatne nastavitve" "Vizualno sporočilo v odzivniku" "Dodatno varnostno kopiranje in shramba" - " ""To je poskusna funkcija"", za katero trenutno izvajamo preskuse. Sporočila v odzivniku bodo morda izbrisana iz strežnika za sporočila v odzivniku. Ni mogoče jamčiti, da bo ta funkcija podprta tudi v prihodnje. Kljub temu bomo veseli vaših povratnih informacij o funkciji." "Nastavitev kode PIN" "Sprememba kode PIN" "Če želite spremeniti kodo PIN, morajo biti vizualna sporočila v odzivniku omogočena" diff --git a/java/com/android/voicemail/impl/res/values-sq/strings.xml b/java/com/android/voicemail/impl/res/values-sq/strings.xml index 472e60c0d2f52a342831f1e339dea924caf10755..b9dfad9a4f4c4eedd5df4e024508e2eaea9c5046 100644 --- a/java/com/android/voicemail/impl/res/values-sq/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sq/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Posta zanore (%s)" "Posta zanore" - "Dridhje" - "Dridhje" - "Tingulli" + + "Cilësimet e përparuara" "Posta zanore vizuale" "Rezervimi dhe hapësira ruajtëse shtesë" - " ""Ky është një funksion eksperimental"" që po e testojmë aktualisht. Kjo mund të fshijë posta zanore nga serveri i postës zanore. Nuk ka garanci për mbështetjen e këtij funksioni në të ardhmen. Megjithatë do të na pëlqente të merrnim komente për funksionin." "Konfiguro kodin PIN" "Ndrysho kodin PIN" "Duhet të aktivizohet posta zanore vizuale për të ndryshuar kodin PIN" diff --git a/java/com/android/voicemail/impl/res/values-sr/strings.xml b/java/com/android/voicemail/impl/res/values-sr/strings.xml index 431d0dfb3ffc73339fe870c98dfccea398fa449a..3608263e2b327d97a69fc45eb0824bf18763be0a 100644 --- a/java/com/android/voicemail/impl/res/values-sr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sr/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Говорна пошта (%s)" "Говорна пошта" - "Вибрација" - "Вибрација" - "Звук" + + "Напредна подешавања" "Визуелна говорна пошта" "Додатне резервне копије и простор" - " ""Ово је експериментална функција"" коју тренутно тестирамо. Тако ће се можда избрисати говорне поруке са сервера говорне поште. Нема гаранција да ће ова функција бити подржана и у будућности. Ипак, желимо да добијамо повратне информације о њој." "Подесите PIN" "Промените PIN" "Морате да омогућите визуелну говорну пошту да бисте променили PIN" diff --git a/java/com/android/voicemail/impl/res/values-sv/strings.xml b/java/com/android/voicemail/impl/res/values-sv/strings.xml index cba2b15c8923824367faaab1bf565650a9f13842..6818b3977919d2c1934c89a348f8f5cd4a96cbd5 100644 --- a/java/com/android/voicemail/impl/res/values-sv/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sv/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Röstbrevlåda (%s)" "Röstbrevlåda" - "Vibrera" - "Vibrera" - "Ljud" + + "Avancerade inställningar" "Visuell röstbrevlåda" "Extra säkerhetskopiering och lagring" - " ""Det här är en experimentfunktion"" som vi för närvarande testar. Den kan potentiellt radera röstmeddelanden på röstbrevlådans server. Vi garanterar inte support för den här funktionen i framtiden. Vi är dock tacksamma för synpunkter om funktionen." "Ställ in pinkod" "Ändra pinkod" "Visuell röstbrevlåda måste vara aktiverat för att ändra pinkoden" diff --git a/java/com/android/voicemail/impl/res/values-sw/strings.xml b/java/com/android/voicemail/impl/res/values-sw/strings.xml index 99de90ca577871db9e4ad5812b051d7a9db88a8f..b08db9a411866edd436d77ac4405edd042c58b2b 100644 --- a/java/com/android/voicemail/impl/res/values-sw/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sw/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ujumbe wa sauti (%s)" "Ujumbe wa sauti" - "Mtetemo" - "Tetema" - "Mlio" + + "Mipangilio ya Kina" "Ujumbe wa Sauti Unaoonekana" "Nafasi ya ziada na hifadhi rudufu" - " ""Hiki ni kipengele cha majaribio"" tunachoijaribu kwa sasa. Huenda kitafuta ujumbe wa sauti kutoka kwenye seva yako ya ujumbe wa sauti. Hakuna hakikisho yoyote kwamba kipengele hiki kitatumika katika siku zijazo. Hata hivyo, tungependa kupata maoni yako kuhusu kipengele hiki." "Weka PIN" "Badilisha PIN" "Lazima uruhusu kipengele cha ujumbe wa sauti unaoonekana ili ubadilishe PIN" diff --git a/java/com/android/voicemail/impl/res/values-ta/strings.xml b/java/com/android/voicemail/impl/res/values-ta/strings.xml index a6c97c112fc645de2328ebaa555232dc6df9d887..f240cdd14efea2a6725277cfb15713e3e174ed30 100644 --- a/java/com/android/voicemail/impl/res/values-ta/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ta/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "குரலஞ்சல் (%s)" "குரலஞ்சல்" - "அதிர்வுறுதல்" - "அதிர்வுறு" - "ஒலி" + + "மேம்பட்ட அமைப்புகள்" "விஷூவல் குரலஞ்சல்" "கூடுதல் காப்புப் பிரதியும் சேமிப்பகமும்" - " தற்போது நாங்கள் நடத்தி வரும் சோதனையில் ""இது ஒரு சோதனை அம்சமாகும்"". இது உங்கள் குரலஞ்சல் சேவையகத்திலிருந்து குரலஞ்சல்களை நீக்க சாத்தியமுள்ளது. இந்த அம்சம் எதிர்காலத்தில் ஆதரிக்கப்படும் என்பதற்கு உத்திரவாதம் இல்லை. இருப்பினும் இந்த அம்சத்தைப் பற்றிய கருத்தை வரவேற்கிறோம்." "பின்னை அமை" "பின்னை மாற்று" "பின்னை மாற்ற, விஷுவல் குரலஞ்சலை இயக்க வேண்டும்" diff --git a/java/com/android/voicemail/impl/res/values-te/strings.xml b/java/com/android/voicemail/impl/res/values-te/strings.xml index 2ad08cffe29e8fcd53e02d1e061414eae10424f5..038ed98f1d82ecf0e8fec3b0eaf05c5ef5c33c1e 100644 --- a/java/com/android/voicemail/impl/res/values-te/strings.xml +++ b/java/com/android/voicemail/impl/res/values-te/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "వాయిస్ మెయిల్ (%s)" "వాయిస్ మెయిల్" - "వైబ్రేషన్" - "వైబ్రేషన్" - "ధ్వని" + + "అధునాతన సెట్టింగ్‌లు" "దృశ్యమాన వాయిస్ మెయిల్" "అదనపు బ్యాకప్ మరియు నిల్వ" - " ""ఇది ప్రయోగాత్మక లక్షణం"" ప్రస్తుతం మేము దీన్ని పరీక్షిస్తున్నాము. దీని వలన మీ వాయిస్ మెయిల్ సర్వర్ నుండి సంభావ్యంగా వాయిస్ మెయిల్‌లు తొలగించబడతాయి. భవిష్యత్తులో ఈ లక్షణానికి మద్దతు ఉంటుందని ఎలాంటి హామీ అందించబడదు. అయితే, లక్షణంపై అభిప్రాయాన్ని అందిస్తే మేము సంతోషిస్తాము." "PINని సెట్ చేయండి" "PINను మార్చండి" "PINని మార్చడానికి తప్పనిసరిగా దృశ్యమాన వాయిస్ మెయిల్‌ను ప్రారంభించాలి" diff --git a/java/com/android/voicemail/impl/res/values-th/strings.xml b/java/com/android/voicemail/impl/res/values-th/strings.xml index 49b07dfa25db0358e7ca75d205e10d05ccb94d5d..d4f52702083e351488c387cbd406269bfdfa22bf 100644 --- a/java/com/android/voicemail/impl/res/values-th/strings.xml +++ b/java/com/android/voicemail/impl/res/values-th/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ข้อความเสียง (%s)" "ข้อความเสียง" - "สั่น" - "สั่น" - "เสียง" + + "การตั้งค่าขั้นสูง" "ภาพแสดงข้อความเสียง" "การสำรองข้อมูลและพื้นที่เก็บข้อมูลเพิ่มเติม" - " ""นี่คือคุณลักษณะทดลอง""ที่เรากำลังทดสอบการใช้งานอยู่ ซึ่งอาจลบข้อความเสียงออกจากเซิร์ฟเวอร์ข้อความเสียงได้ เราไม่รับประกันว่าจะรองรับคุณลักษณะนี้ในอนาคต แต่ยินดีรับฟังความคิดเห็น" "ตั้งค่า PIN" "เปลี่ยน PIN" "ต้องเปิดใช้ข้อความเสียงพร้อมภาพเพื่อเปลี่ยน PIN" diff --git a/java/com/android/voicemail/impl/res/values-tl/strings.xml b/java/com/android/voicemail/impl/res/values-tl/strings.xml index 62623b63342de800fd83df751ada2157ee02ca98..184f27edba1fbf91f93c21275178b4ed816ac220 100644 --- a/java/com/android/voicemail/impl/res/values-tl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-tl/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Voicemail (%s)" "Voicemail" - "I-vibrate" - "I-vibrate" - "Tunog" + + "Mga Advanced na Setting" "Visual na Voicemail" "Karagdagang backup at storage" - " ""Eksperimental na feature ito"" na kasalukuyan naming sinusubukan. Posible nitong i-delete ang mga voicemail mula sa iyong server ng voicemail. Walang garantiyang susuportahan ang feature na ito sa hinaharap. Gayunpaman, gusto naming makakuha ng feedback tungkol sa feature." "Magtakda ng PIN" "Palitan ang PIN" "Dapat naka-enable ang visual na voicemail upang palitan ang PIN" diff --git a/java/com/android/voicemail/impl/res/values-tr/strings.xml b/java/com/android/voicemail/impl/res/values-tr/strings.xml index aed722a11fcbb2ce9956720cc7df272345c3eb3c..2b36fba34d641cc717400d09dfdcac6372cd0083 100644 --- a/java/com/android/voicemail/impl/res/values-tr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-tr/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Sesli mesaj (%s)" "Sesli mesaj" - "Titreşim" - "Titreşim" - "Ses" + + "Gelişmiş Ayarlar" "Görsel Sesli Mesaj" "Ekstra yedekleme ve depolama alanı" - " ""Bu, test etmekte olduğumuz ""deneysel bir özelliktir"". Bu özellik, sesli mesaj sunucunuzdaki mesajların silinmesine neden olabilir ve gelecekte desteklenmeyebilir. Yine de özellikle ilgili geri bildiriminizi öğrenmek isteriz." "PIN belirleyin" "PIN\'i değiştirin" "PIN\'i değiştirebilmek için görsel sesli mesaj etkinleştirilmelidir" diff --git a/java/com/android/voicemail/impl/res/values-uk/strings.xml b/java/com/android/voicemail/impl/res/values-uk/strings.xml index c3cbee6815aef461efa35c106cd28f44d78cd7a8..5e4ab77c03b592cc373e902a8b639b07b0e279b9 100644 --- a/java/com/android/voicemail/impl/res/values-uk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-uk/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Голосова пошта (%s)" "Голосова пошта" - "Вібросигнал" - "Вібросигнал" - "Звук" + + "Розширені налаштування" "Візуальна голосова пошта" "Додаткова пам’ять і резервне копіювання" - " ""Це експериментальна функція,"" яку ми зараз тестуємо. У результаті її використання голосові повідомлення може бути видалено із сервера голосової пошти. Ми не гарантуємо, що ця функція підтримуватиметься в майбутньому, однак хочемо отримати відгук про неї." "Установити PIN-код" "Змінити PIN-код" "Щоб змінити PIN-код, потрібно ввімкнути візуальну голосову пошту" diff --git a/java/com/android/voicemail/impl/res/values-ur/strings.xml b/java/com/android/voicemail/impl/res/values-ur/strings.xml index 201e6e91076f7795a274ed64569f1802f1137b3c..ae6e98def003fd8136b183bea4db456966c30150 100644 --- a/java/com/android/voicemail/impl/res/values-ur/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ur/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "صوتی میل (%s)" "صوتی میل" - "ارتعاش" - "ارتعاش" - "آواز" + + "اعلی ترتیبات" "بصری صوتی میل" "اضافی بیک اپ اور اسٹوریج" - " ""یہ ایک تجرباتی خصوصیت ہے"" جسے ابھی ہم ٹیسٹ کر رہے ہیں۔ یہ ممکنہ طور پر آپ کے صوتی میل سرور پر سے آپ کی صوتی میلز کو حذف کر دے گی۔ مستقبل میں اس خصوصیت کی معاونت کی کوئی ضمانت نہیں ہے۔ لیکن ہم اس خصوصیت پر تاثرات پسند کریں گے۔" "‏PIN سیٹ کریں" "‏PIN تبدیل کریں" "‏PIN تبدیل کرنے کیلئے بصری صوتی میل اہل ہونی چاہئیے" diff --git a/java/com/android/voicemail/impl/res/values-uz/strings.xml b/java/com/android/voicemail/impl/res/values-uz/strings.xml index 7f26475ec45446a06602ddb7bbecafbadf141575..f458aee7b088a38d9e05f3d5a9e25f26d72779fa 100644 --- a/java/com/android/voicemail/impl/res/values-uz/strings.xml +++ b/java/com/android/voicemail/impl/res/values-uz/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ovozli pochta (%s)" "Ovozli pochta" - "Tebranish" - "Tebranish" - "Ovoz" + + "Kengaytirilgan sozlamalar" "Vizual ovozli pochta" "Zaxira. va saqlash u-n qo‘shimcha xotira" - " ""Bu – tajribaviy xususiyat bo‘lib,"" u ayni vaqtda sinovdan o‘tkazilmoqda. Sizning ovozli xabarlaringiz, ehtimol, ovozli pochta serveridan o‘chirib tashlanadi. Bu xususiyatning keyinchalik qo‘llab-quvvatlanishi kafolatlanmaydi. Shunday bo‘lsa-da, u haqda fikr-mulohaza bildirishingizni xohlaymiz." "PIN kod o‘rnatish" "PIN kodni o‘zgartirish" "PIN kodni o‘zgartirish uchun vizual ovozli pochtani yoqish lozim." diff --git a/java/com/android/voicemail/impl/res/values-vi/strings.xml b/java/com/android/voicemail/impl/res/values-vi/strings.xml index a0b25f803e2d2b1427e1b34a7d6e67eb4f9bf389..c0bfa8183513027d5e53995d20442f788c98a1d8 100644 --- a/java/com/android/voicemail/impl/res/values-vi/strings.xml +++ b/java/com/android/voicemail/impl/res/values-vi/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Thư thoại %s" "Thư thoại" - "Rung" - "Rung" - "Âm báo" + + "Cài đặt nâng cao" "Thư thoại kèm theo hình ảnh" "Bộ nhớ và bản sao lưu bổ sung" - " ""Đây là một tính năng thử nghiệm"" chúng tôi hiện đang thử nghiệm. Tính năng này có khả năng sẽ xóa thư thoại khỏi máy chủ thư thoại của bạn. Không có đảm bảo về việc hỗ trợ tính năng này trong tương lai. Mặc dù vậy, chúng tôi vẫn mong muốn nhận được phản hồi về tính năng này." "Đặt mã PIN" "Thay đổi mã PIN" "Phải bật thư thoại kèm theo hình ảnh để thay đổi mã PIN" diff --git a/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml b/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml index 9bfbe368d2556795c9e7489b3e1dd40e35c9151e..66b058b1f4d29a0b9dd890e6ac523fa19eebe865 100644 --- a/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "语音邮件(%s)" "语音邮件" - "振动" - "振动" - "提示音" + + "高级设置" "可视语音信箱" "额外存储空间和备份功能" - " ""这是一项试验性功能"" 我们目前正在进行测试。使用此功能可能会将语音邮件从您的语音邮件服务器上删除。我们不保证将来会支持此功能,但希望能收到针对此功能的反馈。" "设置 PIN 码" "更改 PIN 码" "必须启用可视语音信箱才可更改 PIN 码" diff --git a/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml b/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml index 6c1ed4d15db402c092b28deb484125547b1b736a..d760687901daaab88bc27b30924cf7ba60e1eec6 100644 --- a/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "留言 (%s)" "留言" - "震動" - "震動" - "音效" + + "進階設定" "視像留言" "額外備份功能和儲存空間" - " ""此為我們目前正在測試的實驗性功能"",有可能會將您的留言從留言伺服器刪除。我們不保證日後會支援此功能,但還是歡迎您提供相關意見。" "設定 PIN" "變更 PIN" "必須啟用視像留言才能變更 PIN" diff --git a/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml b/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml index 0af6ed1523823d601e1bb8068767342319c1f9ed..2b4de45d961dabf8c2e66348d7f64680ecdf4a7a 100644 --- a/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "語音信箱 (%s)" "語音信箱" - "震動" - "震動" - "音效" + + "進階設定" "視覺化語音信箱" "額外的備份功能和儲存空間" - " ""這是實驗性功能"",目前正在測試階段,而且可能會從你的語音信箱伺服器中刪除語音留言。我們不保證日後會支援此功能,但還是希望聽聽你的寶貴意見。" "設定 PIN" "變更 PIN" "必須啟用視覺化語音信箱才能變更 PIN" diff --git a/java/com/android/voicemail/impl/res/values-zu/strings.xml b/java/com/android/voicemail/impl/res/values-zu/strings.xml index 81d4d3548b79076529bba022763cac4da97385de..1debac61be2f9196bba6dc8f5abe1ad14fa13a82 100644 --- a/java/com/android/voicemail/impl/res/values-zu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zu/strings.xml @@ -18,13 +18,11 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ivoyisimeyili (%s)" "Ivoyisimeyili" - "Dlidlizela" - "Dlidlizela" - "Umsindo" + + "Izilungiselelo ezithuthukisiwe" "Ivoyisimeyili ebonakalayo" "Isipele esingeziwe nesitoreji" - " ""Lesi isici sokuhlola"" manje esisihlolayo. Lokhu kunamandla okususa amavoyisimeyili kusukela kuseva yakho yevoyisimeyili. Azikho iziqinisekiso zokusekela lesi sici ngokuzayo. Singathanda impendulo kusici yize kunjalo." "Setha i-PIN" "Shintsha i-PIN" "Ivoyisimeyili ebonakalayo kumele inikwe amandla ukuze ishintshe i-PIN" diff --git a/java/com/android/voicemail/impl/res/values/strings.xml b/java/com/android/voicemail/impl/res/values/strings.xml index c8085619b51beff745807f702e20b59770cbf108..375a1e9bab81463458036ede697f312206e6b7d7 100644 --- a/java/com/android/voicemail/impl/res/values/strings.xml +++ b/java/com/android/voicemail/impl/res/values/strings.xml @@ -23,19 +23,12 @@ Voicemail - voicemail_notification_ringtone_key - - voicemail_notification_vibrate_key - - - Vibrate - - Vibrate + voicemail_notification_key - - Sound + Notifications voicemail_advanced_settings_key @@ -59,11 +52,6 @@ Extra backup and storage - - - This is a experimental feature we are currently testing. This will potentially delete voicemails from your voicemail server. There are no guarantees of supporting this feature in the future. We would love feedback on the feature though." - - Set PIN diff --git a/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml b/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml index 53fd57f7eed128573998496b47405ebffff05350..50510905c2b2e84a986afb3268c4dde85bb31d42 100644 --- a/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml +++ b/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml @@ -17,16 +17,9 @@ - - - + + + + vvm_carrier_flag_20610 + + + + + + 8082 + + + + vvm_type_omtp + + + + + + + @@ -46,6 +70,30 @@ + + + vvm_carrier_flag_20610 + + + + + + 64085 + + + + vvm_type_omtp + + + + + + + @@ -85,6 +133,22 @@ + + + vvm_carrier_flag_302220 + + + + + 7723 + vvm_type_omtp + + + diff --git a/java/com/android/voicemail/impl/scheduling/BaseTask.java b/java/com/android/voicemail/impl/scheduling/BaseTask.java index 4cc6dd59e8e9602b33a60b5478d8f9e0f4aec0f3..bbdca8c88d0defcfa9032d2df191426df03af65d 100644 --- a/java/com/android/voicemail/impl/scheduling/BaseTask.java +++ b/java/com/android/voicemail/impl/scheduling/BaseTask.java @@ -18,12 +18,14 @@ package com.android.voicemail.impl.scheduling; import android.content.Context; import android.content.Intent; +import android.os.Bundle; import android.os.SystemClock; import android.support.annotation.CallSuper; import android.support.annotation.MainThread; import android.support.annotation.NonNull; import android.support.annotation.WorkerThread; import android.telecom.PhoneAccountHandle; +import com.android.dialer.proguard.UsedByReflection; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.NeededForTesting; import java.util.ArrayList; @@ -33,10 +35,15 @@ import java.util.List; * Provides common utilities for task implementations, such as execution time and managing {@link * Policy} */ +@UsedByReflection(value = "Tasks.java") public abstract class BaseTask implements Task { private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle"; + private static final String EXTRA_EXECUTION_TIME = "extra_execution_time"; + + private Bundle mExtras; + private Context mContext; private int mId; @@ -58,7 +65,7 @@ public abstract class BaseTask implements Task { /** * Modify the task ID to prevent arbitrary task from executing. Can only be called before {@link - * #onCreate(Context, Intent, int, int)} returns. + * #onCreate(Context, Bundle)} returns. */ @MainThread public void setId(int id) { @@ -86,8 +93,7 @@ public abstract class BaseTask implements Task { return mPhoneAccountHandle; } /** - * Should be call in the constructor or {@link Policy#onCreate(BaseTask, Intent, int, int)} will - * be missed. + * Should be call in the constructor or {@link Policy#onCreate(BaseTask, Bundle)} will be missed. */ @MainThread public BaseTask addPolicy(Policy policy) { @@ -107,6 +113,7 @@ public abstract class BaseTask implements Task { mHasFailed = true; } + /** @param timeMillis the time since epoch, in milliseconds. */ @MainThread public void setExecutionTime(long timeMillis) { Assert.isMainThread(); @@ -126,12 +133,12 @@ public abstract class BaseTask implements Task { } /** - * Creates an intent that can be used to start the {@link TaskSchedulerService}. Derived class + * Creates an intent that can be used to be broadcast to the {@link TaskReceiver}. Derived class * should build their intent upon this. */ public static Intent createIntent( Context context, Class task, PhoneAccountHandle phoneAccountHandle) { - Intent intent = TaskSchedulerService.createIntent(context, task); + Intent intent = Tasks.createIntent(context, task); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); return intent; } @@ -141,13 +148,28 @@ public abstract class BaseTask implements Task { return new TaskId(mId, mPhoneAccountHandle); } + @Override + public Bundle toBundle() { + mExtras.putLong(EXTRA_EXECUTION_TIME, mExecutionTime); + return mExtras; + } + @Override @CallSuper - public void onCreate(Context context, Intent intent, int flags, int startId) { + public void onCreate(Context context, Bundle extras) { mContext = context; - mPhoneAccountHandle = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE); + mExtras = extras; + mPhoneAccountHandle = extras.getParcelable(EXTRA_PHONE_ACCOUNT_HANDLE); for (Policy policy : mPolicies) { - policy.onCreate(this, intent, flags, startId); + policy.onCreate(this, extras); + } + } + + @Override + @CallSuper + public void onRestore(Bundle extras) { + if (mExtras.containsKey(EXTRA_EXECUTION_TIME)) { + mExecutionTime = extras.getLong(EXTRA_EXECUTION_TIME); } } diff --git a/java/com/android/voicemail/impl/scheduling/BlockerTask.java b/java/com/android/voicemail/impl/scheduling/BlockerTask.java index 353508d56e06bc3f4a9e8bac054ef8f46d49c0ac..1c8badaed7b4f05544e8e9928500b52422f18cb2 100644 --- a/java/com/android/voicemail/impl/scheduling/BlockerTask.java +++ b/java/com/android/voicemail/impl/scheduling/BlockerTask.java @@ -17,10 +17,12 @@ package com.android.voicemail.impl.scheduling; import android.content.Context; -import android.content.Intent; +import android.os.Bundle; +import com.android.dialer.proguard.UsedByReflection; import com.android.voicemail.impl.VvmLog; /** Task to block another task of the same ID from being queued for a certain amount of time. */ +@UsedByReflection(value = "Tasks.java") public class BlockerTask extends BaseTask { private static final String TAG = "BlockerTask"; @@ -33,10 +35,10 @@ public class BlockerTask extends BaseTask { } @Override - public void onCreate(Context context, Intent intent, int flags, int startId) { - super.onCreate(context, intent, flags, startId); - setId(intent.getIntExtra(EXTRA_TASK_ID, TASK_INVALID)); - setExecutionTime(getTimeMillis() + intent.getIntExtra(EXTRA_BLOCK_FOR_MILLIS, 0)); + public void onCreate(Context context, Bundle extras) { + super.onCreate(context, extras); + setId(extras.getInt(EXTRA_TASK_ID, TASK_INVALID)); + setExecutionTime(getTimeMillis() + extras.getInt(EXTRA_BLOCK_FOR_MILLIS, 0)); } @Override @@ -46,6 +48,6 @@ public class BlockerTask extends BaseTask { @Override public void onDuplicatedTaskAdded(Task task) { - VvmLog.v(TAG, task.toString() + "blocked, " + getReadyInMilliSeconds() + "millis remaining"); + VvmLog.i(TAG, task + "blocked, " + getReadyInMilliSeconds() + "millis remaining"); } } diff --git a/java/com/android/voicemail/impl/scheduling/MinimalIntervalPolicy.java b/java/com/android/voicemail/impl/scheduling/MinimalIntervalPolicy.java index 8b2fe709884acca54279d4c1d941cefc6997a674..342b56e8a9b8f48b696a9a5936db1b7c89e34c1c 100644 --- a/java/com/android/voicemail/impl/scheduling/MinimalIntervalPolicy.java +++ b/java/com/android/voicemail/impl/scheduling/MinimalIntervalPolicy.java @@ -17,6 +17,7 @@ package com.android.voicemail.impl.scheduling; import android.content.Intent; +import android.os.Bundle; import com.android.voicemail.impl.scheduling.Task.TaskId; /** @@ -35,7 +36,7 @@ public class MinimalIntervalPolicy implements Policy { } @Override - public void onCreate(BaseTask task, Intent intent, int flags, int startId) { + public void onCreate(BaseTask task, Bundle extras) { mTask = task; mId = mTask.getId(); } @@ -47,10 +48,10 @@ public class MinimalIntervalPolicy implements Policy { public void onCompleted() { if (!mTask.hasFailed()) { Intent intent = - mTask.createIntent(mTask.getContext(), BlockerTask.class, mId.phoneAccountHandle); + BaseTask.createIntent(mTask.getContext(), BlockerTask.class, mId.phoneAccountHandle); intent.putExtra(BlockerTask.EXTRA_TASK_ID, mId.id); intent.putExtra(BlockerTask.EXTRA_BLOCK_FOR_MILLIS, mBlockForMillis); - mTask.getContext().startService(intent); + mTask.getContext().sendBroadcast(intent); } } diff --git a/java/com/android/voicemail/impl/scheduling/Policy.java b/java/com/android/voicemail/impl/scheduling/Policy.java index 6077821919bb2d013704eb33a48e5133a470bf32..9624aeb7da0091fb9cfa6b5bc8699d71b54f43ad 100644 --- a/java/com/android/voicemail/impl/scheduling/Policy.java +++ b/java/com/android/voicemail/impl/scheduling/Policy.java @@ -16,7 +16,7 @@ package com.android.voicemail.impl.scheduling; -import android.content.Intent; +import android.os.Bundle; /** * A set of listeners managed by {@link BaseTask} for common behaviors such as retrying. Call {@link @@ -24,7 +24,7 @@ import android.content.Intent; */ public interface Policy { - void onCreate(BaseTask task, Intent intent, int flags, int startId); + void onCreate(BaseTask task, Bundle extras); void onBeforeExecute(); diff --git a/java/com/android/voicemail/impl/scheduling/PostponePolicy.java b/java/com/android/voicemail/impl/scheduling/PostponePolicy.java index e24df0c7a1ba7a189453503742ed97b55322478f..46773b53a7a10f43eb1bbb05280838fe553a2f90 100644 --- a/java/com/android/voicemail/impl/scheduling/PostponePolicy.java +++ b/java/com/android/voicemail/impl/scheduling/PostponePolicy.java @@ -16,7 +16,7 @@ package com.android.voicemail.impl.scheduling; -import android.content.Intent; +import android.os.Bundle; import com.android.voicemail.impl.VvmLog; /** @@ -37,7 +37,7 @@ public class PostponePolicy implements Policy { } @Override - public void onCreate(BaseTask task, Intent intent, int flags, int startId) { + public void onCreate(BaseTask task, Bundle extras) { mTask = task; mTask.setExecutionTime(mTask.getTimeMillis() + mPostponeMillis); } @@ -62,7 +62,7 @@ public class PostponePolicy implements Policy { if (mTask.hasStarted()) { return; } - VvmLog.d(TAG, "postponing " + mTask); + VvmLog.i(TAG, "postponing " + mTask); mTask.setExecutionTime(mTask.getTimeMillis() + mPostponeMillis); } } diff --git a/java/com/android/voicemail/impl/scheduling/RetryPolicy.java b/java/com/android/voicemail/impl/scheduling/RetryPolicy.java index a8e4a3d3cfb03d872b60d5f829a1845060833f3f..c408bdc4a161a00c560649a6fd01d91b881972c4 100644 --- a/java/com/android/voicemail/impl/scheduling/RetryPolicy.java +++ b/java/com/android/voicemail/impl/scheduling/RetryPolicy.java @@ -17,6 +17,7 @@ package com.android.voicemail.impl.scheduling; import android.content.Intent; +import android.os.Bundle; import android.telecom.PhoneAccountHandle; import com.android.voicemail.impl.VoicemailStatus; import com.android.voicemail.impl.VvmLog; @@ -60,11 +61,11 @@ public class RetryPolicy implements Policy { } @Override - public void onCreate(BaseTask task, Intent intent, int flags, int startId) { + public void onCreate(BaseTask task, Bundle extras) { mTask = task; - mRetryCount = intent.getIntExtra(EXTRA_RETRY_COUNT, 0); + mRetryCount = extras.getInt(EXTRA_RETRY_COUNT, 0); if (mRetryCount > 0) { - VvmLog.d( + VvmLog.i( TAG, "retry #" + mRetryCount + " for " + mTask + " queued, executing in " + mRetryDelayMillis); mTask.setExecutionTime(mTask.getTimeMillis() + mRetryDelayMillis); @@ -85,10 +86,10 @@ public class RetryPolicy implements Policy { public void onCompleted() { if (!mFailed || !hasMoreRetries()) { if (!mFailed) { - VvmLog.d(TAG, mTask.toString() + " completed successfully"); + VvmLog.i(TAG, mTask + " completed successfully"); } if (!hasMoreRetries()) { - VvmLog.d(TAG, "Retry limit for " + mTask + " reached"); + VvmLog.i(TAG, "Retry limit for " + mTask + " reached"); } VvmLog.i(TAG, "committing deferred status: " + mVoicemailStatusEditor.getValues()); mVoicemailStatusEditor.deferredApply(); @@ -98,7 +99,7 @@ public class RetryPolicy implements Policy { Intent intent = mTask.createRestartIntent(); intent.putExtra(EXTRA_RETRY_COUNT, mRetryCount + 1); - mTask.getContext().startService(intent); + mTask.getContext().sendBroadcast(intent); } @Override diff --git a/java/com/android/voicemail/impl/scheduling/Task.java b/java/com/android/voicemail/impl/scheduling/Task.java index 2d08f5b039dd00da52175546bd21c1756e281651..484a6262e29cb60b61faec027429f0a032fd3dde 100644 --- a/java/com/android/voicemail/impl/scheduling/Task.java +++ b/java/com/android/voicemail/impl/scheduling/Task.java @@ -17,26 +17,24 @@ package com.android.voicemail.impl.scheduling; import android.content.Context; -import android.content.Intent; +import android.os.Bundle; import android.support.annotation.MainThread; import android.support.annotation.WorkerThread; import android.telecom.PhoneAccountHandle; import java.util.Objects; /** - * A task for {@link TaskSchedulerService} to execute. Since the task is sent through a intent to - * the scheduler, The task must be constructable with the intent. Specifically, It must have a - * constructor with zero arguments, and have all relevant data packed inside the intent. Use {@link - * TaskSchedulerService#createIntent(Context, Class)} to create a intent that will construct the - * Task. + * A task for {@link TaskExecutor} to execute. Since the task is sent through a bundle to the + * scheduler, The task must be constructable with the bundle. Specifically, It must have a + * constructor with zero arguments, and have all relevant data packed inside the bundle. Use {@link + * Tasks#createIntent(Context, Class)} to create a intent that will construct the Task. * *

Only {@link #onExecuteInBackgroundThread()} is run on the worker thread. */ public interface Task { - /** * TaskId to indicate it has not be set. If a task does not provide a default TaskId it should be - * set before {@link Task#onCreate(Context, Intent, int, int) returns} + * set before {@link Task#onCreate(Context, Bundle)} returns */ int TASK_INVALID = -1; @@ -49,6 +47,7 @@ public interface Task { int TASK_UPLOAD = 1; int TASK_SYNC = 2; int TASK_ACTIVATION = 3; + int TASK_STATUS_CHECK = 4; /** * Used to differentiate between types of tasks. If a task with the same TaskId is already in the @@ -87,13 +86,34 @@ public interface Task { TaskId getId(); + /** + * Serializes the task into a bundle, which will be stored in a {@link android.app.job.JobInfo} + * and used to reconstruct the task even if the app is terminated. The task will be initialized + * with {@link #onCreate(Context, Bundle)}. + */ + Bundle toBundle(); + + /** + * A task object is created through reflection, calling the default constructor. The actual + * initialization is done in this method. If the task is not a new instance, but being restored + * from a bundle, {@link #onRestore(Bundle)} will be called afterwards. + */ + @MainThread + void onCreate(Context context, Bundle extras); + + /** + * Called after {@link #onCreate(Context, Bundle)} if the task is being restored from a Bundle + * instead creating a new instance. For example, if the task is stored in {@link + * TaskSchedulerJobService} during a long sleep, this will be called when the job is ran again and + * the tasks are being restored from the saved state. + */ @MainThread - void onCreate(Context context, Intent intent, int flags, int startId); + void onRestore(Bundle extras); /** * @return number of milliSeconds the scheduler should wait before running this task. A value less - * than {@link TaskSchedulerService#READY_TOLERANCE_MILLISECONDS} will be considered ready. If - * no tasks are ready, the scheduler will sleep for this amount of time before doing another + * than {@link TaskExecutor#READY_TOLERANCE_MILLISECONDS} will be considered ready. If no + * tasks are ready, the scheduler will sleep for this amount of time before doing another * check (it will still wake if a new task is added). The first task in the queue that is * ready will be executed. */ diff --git a/java/com/android/voicemail/impl/scheduling/TaskExecutor.java b/java/com/android/voicemail/impl/scheduling/TaskExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..e3b718e503d47542ae043a5e6957f3d254c26eb5 --- /dev/null +++ b/java/com/android/voicemail/impl/scheduling/TaskExecutor.java @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2017 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.voicemail.impl.scheduling; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.support.annotation.MainThread; +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import android.support.annotation.WorkerThread; +import com.android.voicemail.impl.Assert; +import com.android.voicemail.impl.NeededForTesting; +import com.android.voicemail.impl.VvmLog; +import com.android.voicemail.impl.scheduling.TaskQueue.NextTask; +import java.util.List; + +/** + * A singleton to queue and run {@link Task} with the {@link android.app.job.JobScheduler}. A task + * is queued by sending a broadcast to {@link TaskReceiver}. The intent should contain enough + * information in {@link Intent#getExtras()} to construct the task (see {@link + * Tasks#createIntent(Context, Class)}). + * + *

The executor will only exist when {@link TaskSchedulerJobService} is running. + * + *

All tasks are ran in the background with a wakelock being held by the {@link + * android.app.job.JobScheduler}, which is between {@link #onStartJob(Job, List)} and {@link + * #finishJobAsync()}. The {@link TaskSchedulerJobService} also has a {@link TaskQueue}, but the + * data is stored in the {@link android.app.job.JobScheduler} instead of the process memory, so if + * the process is killed the queued tasks will be restored. If a new task is added, a new {@link + * TaskSchedulerJobService} will be scheduled to run the task. If the job is already scheduled, the + * new task will be pushed into the queue of the scheduled job. If the job is already running, the + * job will be queued in process memory. + * + *

Only one task will be ran at a time, and same task cannot exist in the queue at the same time. + * Refer to {@link TaskQueue} for queuing and execution order. + * + *

If there are still tasks in the queue but none are executable immediately, the service will + * enter a "sleep", pushing all remaining task into a new job and end the current job. + * + *

The executor will be started when {@link TaskSchedulerJobService} is running, and stopped when + * there are no more tasks in the queue or when the executor is put to sleep. + * + *

{@link android.app.job.JobScheduler} is not used directly due to: + * + *

    + *
  • The {@link android.telecom.PhoneAccountHandle} used to differentiate task can not be easily + * mapped into an integer for job id + *
  • A job cannot be mutated to store information such as retry count. + *
+ */ +@TargetApi(VERSION_CODES.O) +final class TaskExecutor { + + /** + * An entity that holds execution resources for the {@link TaskExecutor} to run, usually a {@link + * android.app.job.JobService}. + */ + interface Job { + + /** + * Signals to Job to end and release its' resources. This is an asynchronous call and may not + * take effect immediately. + */ + @MainThread + void finishAsync(); + + /** Whether the call to {@link #finishAsync()} has actually taken effect. */ + @MainThread + boolean isFinished(); + } + + private static final String TAG = "VvmTaskExecutor"; + + private static final int READY_TOLERANCE_MILLISECONDS = 100; + + /** + * Threshold to determine whether to do a short or long sleep when a task is scheduled in the + * future. + * + *

A short sleep will continue the job and use {@link Handler#postDelayed(Runnable, long)} to + * wait for the next task. + * + *

A long sleep will finish the job and schedule a new one. The exact execution time is + * subjected to {@link android.app.job.JobScheduler} battery optimization, and is not exact. + */ + private static final int SHORT_SLEEP_THRESHOLD_MILLISECONDS = 10_000; + /** + * When there are no more tasks to be run the service should be stopped. But when all tasks has + * finished there might still be more tasks in the message queue waiting to be processed, + * especially the ones submitted in {@link Task#onCompleted()}. Wait for a while before stopping + * the service to make sure there are no pending messages. + */ + private static final int STOP_DELAY_MILLISECONDS = 5_000; + + /** Interval between polling of whether the job is finished. */ + private static final int TERMINATE_POLLING_INTERVAL_MILLISECONDS = 1_000; + + // The thread to run tasks on + private final WorkerThreadHandler workerThreadHandler; + + private static TaskExecutor instance; + + /** + * Used by tests to turn task handling into a single threaded process by calling {@link + * Handler#handleMessage(Message)} directly + */ + private MessageSender messageSender = new MessageSender(); + + private final MainThreadHandler mainThreadHandler; + + private final Context context; + + /** Main thread only, access through {@link #getTasks()} */ + private final TaskQueue tasks = new TaskQueue(); + + private boolean isWorkerThreadBusy = false; + + private boolean isTerminating = false; + + private Job job; + + private final Runnable stopServiceWithDelay = + new Runnable() { + @MainThread + @Override + public void run() { + VvmLog.i(TAG, "Stopping service"); + if (!isJobRunning() || isTerminating()) { + VvmLog.e(TAG, "Service already stopped"); + return; + } + scheduleJobAndTerminate(0, true); + } + }; + + /** + * Reschedule the {@link TaskSchedulerJobService} and terminate the executor when the {@link Job} + * is truly finished. If the job is still not finished, this runnable will requeue itself on the + * main thread. The requeue is only expected to happen a few times. + */ + private class JobFinishedPoller implements Runnable { + + private final long delayMillis; + private final boolean isNewJob; + private int invocationCounter = 0; + + JobFinishedPoller(long delayMillis, boolean isNewJob) { + this.delayMillis = delayMillis; + this.isNewJob = isNewJob; + } + + @Override + public void run() { + // The job should be finished relatively quickly. Assert to make sure this assumption is true. + Assert.isTrue(invocationCounter < 10); + invocationCounter++; + if (job.isFinished()) { + VvmLog.i("JobFinishedPoller.run", "Job finished"); + if (!getTasks().isEmpty()) { + TaskSchedulerJobService.scheduleJob( + context, serializePendingTasks(), delayMillis, isNewJob); + tasks.clear(); + } + terminate(); + return; + } + VvmLog.w("JobFinishedPoller.run", "Job still running"); + mainThreadHandler.postDelayed(this, TERMINATE_POLLING_INTERVAL_MILLISECONDS); + } + }; + + /** Should attempt to run the next task when a task has finished or been added. */ + private boolean taskAutoRunDisabledForTesting = false; + + /** Handles execution of the background task in teh worker thread. */ + @VisibleForTesting + final class WorkerThreadHandler extends Handler { + + public WorkerThreadHandler(Looper looper) { + super(looper); + } + @Override + @WorkerThread + public void handleMessage(Message msg) { + Assert.isNotMainThread(); + Task task = (Task) msg.obj; + try { + VvmLog.i(TAG, "executing task " + task); + task.onExecuteInBackgroundThread(); + } catch (Throwable throwable) { + VvmLog.e(TAG, "Exception while executing task " + task + ":", throwable); + } + + Message schedulerMessage = mainThreadHandler.obtainMessage(); + schedulerMessage.obj = task; + messageSender.send(schedulerMessage); + } + } + + /** Handles completion of the background task in the main thread. */ + @VisibleForTesting + final class MainThreadHandler extends Handler { + + public MainThreadHandler(Looper looper) { + super(looper); + } + + @Override + @MainThread + public void handleMessage(Message msg) { + Assert.isMainThread(); + Task task = (Task) msg.obj; + getTasks().remove(task); + task.onCompleted(); + isWorkerThreadBusy = false; + if (!isJobRunning() || isTerminating()) { + // TaskExecutor was terminated when the task is running in background, don't need to run the + // next task or terminate again + return; + } + maybeRunNextTask(); + } + } + + /** Starts a new TaskExecutor. May only be called by {@link TaskSchedulerJobService}. */ + @MainThread + static void createRunningInstance(Context context) { + Assert.isMainThread(); + Assert.isTrue(instance == null); + instance = new TaskExecutor(context); + } + + /** @return the currently running instance, or {@code null} if the executor is not running. */ + @MainThread + @Nullable + static TaskExecutor getRunningInstance() { + return instance; + } + + private TaskExecutor(Context context) { + this.context = context; + HandlerThread thread = new HandlerThread("VvmTaskExecutor"); + thread.start(); + + workerThreadHandler = new WorkerThreadHandler(thread.getLooper()); + mainThreadHandler = new MainThreadHandler(Looper.getMainLooper()); + } + + @VisibleForTesting + void terminate() { + VvmLog.i(TAG, "terminated"); + Assert.isMainThread(); + job = null; + workerThreadHandler.getLooper().quit(); + instance = null; + TaskReceiver.resendDeferredBroadcasts(context); + } + + @MainThread + void addTask(Task task) { + Assert.isMainThread(); + getTasks().add(task); + VvmLog.i(TAG, task + " added"); + mainThreadHandler.removeCallbacks(stopServiceWithDelay); + maybeRunNextTask(); + } + + @MainThread + @VisibleForTesting + TaskQueue getTasks() { + Assert.isMainThread(); + return tasks; + } + + @MainThread + private void maybeRunNextTask() { + Assert.isMainThread(); + + if (isWorkerThreadBusy) { + return; + } + if (taskAutoRunDisabledForTesting) { + // If taskAutoRunDisabledForTesting is true, runNextTask() must be explicitly called + // to run the next task. + return; + } + + runNextTask(); + } + + @VisibleForTesting + @MainThread + void runNextTask() { + Assert.isMainThread(); + if (getTasks().isEmpty()) { + prepareStop(); + return; + } + NextTask nextTask = getTasks().getNextTask(READY_TOLERANCE_MILLISECONDS); + + if (nextTask.task != null) { + nextTask.task.onBeforeExecute(); + Message message = workerThreadHandler.obtainMessage(); + message.obj = nextTask.task; + isWorkerThreadBusy = true; + messageSender.send(message); + return; + } + VvmLog.i(TAG, "minimal wait time:" + nextTask.minimalWaitTimeMillis); + if (!taskAutoRunDisabledForTesting && nextTask.minimalWaitTimeMillis != null) { + // No tasks are currently ready. Sleep until the next one should be. + // If a new task is added during the sleep the service will wake immediately. + sleep(nextTask.minimalWaitTimeMillis); + } + } + + @MainThread + private void sleep(long timeMillis) { + VvmLog.i(TAG, "sleep for " + timeMillis + " millis"); + if (timeMillis < SHORT_SLEEP_THRESHOLD_MILLISECONDS) { + mainThreadHandler.postDelayed( + new Runnable() { + @Override + public void run() { + maybeRunNextTask(); + } + }, + timeMillis); + return; + } + scheduleJobAndTerminate(timeMillis, false); + } + + private List serializePendingTasks() { + return getTasks().toBundles(); + } + + private void prepareStop() { + VvmLog.i( + TAG, + "no more tasks, stopping service if no task are added in " + + STOP_DELAY_MILLISECONDS + + " millis"); + mainThreadHandler.postDelayed(stopServiceWithDelay, STOP_DELAY_MILLISECONDS); + } + + @NeededForTesting + static class MessageSender { + + public void send(Message message) { + message.sendToTarget(); + } + } + + @NeededForTesting + void setTaskAutoRunDisabledForTest(boolean value) { + taskAutoRunDisabledForTesting = value; + } + + @NeededForTesting + void setMessageSenderForTest(MessageSender sender) { + messageSender = sender; + } + + /** + * The {@link TaskSchedulerJobService} has started and all queued task should be executed in the + * worker thread. + */ + @MainThread + public void onStartJob(Job job, List pendingTasks) { + VvmLog.i(TAG, "onStartJob"); + this.job = job; + tasks.fromBundles(context, pendingTasks); + maybeRunNextTask(); + } + + /** + * The {@link TaskSchedulerJobService} is being terminated by the system (timeout or network + * lost). A new job will be queued to resume all pending tasks. The current unfinished job may be + * ran again. + */ + @MainThread + public void onStopJob() { + VvmLog.e(TAG, "onStopJob"); + if (isJobRunning() && !isTerminating()) { + scheduleJobAndTerminate(0, true); + } + } + + /** + * Send all pending tasks and schedule a new {@link TaskSchedulerJobService}. The current executor + * will start the termination process, but restarted when the scheduled job runs in the future. + * + * @param delayMillis the delay before stating the job, see {@link + * android.app.job.JobInfo.Builder#setMinimumLatency(long)}. This must be 0 if {@code + * isNewJob} is true. + * @param isNewJob a new job will be requested to run immediately, bypassing all requirements. + */ + @MainThread + @VisibleForTesting + void scheduleJobAndTerminate(long delayMillis, boolean isNewJob) { + Assert.isMainThread(); + finishJobAsync(); + mainThreadHandler.post(new JobFinishedPoller(delayMillis, isNewJob)); + } + + /** + * Whether the TaskExecutor is still terminating. {@link TaskReceiver} should defer all new task + * until {@link #getRunningInstance()} returns {@code null} so a new job can be started. {@link + * #scheduleJobAndTerminate(long, boolean)} does not run immediately because the job can only be + * scheduled after the main thread has returned. The TaskExecutor will be in a intermediate state + * between scheduleJobAndTerminate() and terminate(). In this state, {@link #getRunningInstance()} + * returns non-null because it has not been fully stopped yet, but the TaskExecutor cannot do + * anything. A new job should not be scheduled either because the current job might still be + * running. + */ + @MainThread + public boolean isTerminating() { + return isTerminating; + } + + /** + * Signals {@link TaskSchedulerJobService} the current session of tasks has finished, and the wake + * lock can be released. Note: this only takes effect after the main thread has been returned. If + * a new job need to be scheduled, it should be posted on the main thread handler instead of + * calling directly. + */ + @MainThread + private void finishJobAsync() { + Assert.isTrue(!isTerminating()); + Assert.isMainThread(); + VvmLog.i(TAG, "finishing Job"); + job.finishAsync(); + isTerminating = true; + mainThreadHandler.removeCallbacks(stopServiceWithDelay); + } + + private boolean isJobRunning() { + return job != null; + } +} diff --git a/java/com/android/voicemail/impl/scheduling/TaskQueue.java b/java/com/android/voicemail/impl/scheduling/TaskQueue.java new file mode 100644 index 0000000000000000000000000000000000000000..fc5aa947a0df7ed4e816d5a5c2fe9b7c96d7f7b3 --- /dev/null +++ b/java/com/android/voicemail/impl/scheduling/TaskQueue.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2017 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.voicemail.impl.scheduling; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import com.android.voicemail.impl.Assert; +import com.android.voicemail.impl.VvmLog; +import com.android.voicemail.impl.scheduling.Task.TaskId; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Queue; + +/** + * A queue that manages priority and duplication of {@link Task}. A task is identified by a {@link + * TaskId}, which consists of an integer representing the operation the task, and a {@link + * android.telecom.PhoneAccountHandle} representing which SIM it is operated on. + */ +class TaskQueue implements Iterable { + + private final Queue queue = new ArrayDeque<>(); + + public List toBundles() { + List result = new ArrayList<>(queue.size()); + for (Task task : queue) { + result.add(Tasks.toBundle(task)); + } + return result; + } + + public void fromBundles(Context context, List pendingTasks) { + Assert.isTrue(queue.isEmpty()); + for (Bundle pendingTask : pendingTasks) { + Task task = Tasks.createTask(context, pendingTask); + task.onRestore(pendingTask); + add(task); + } + } + + /** + * Add a new task to the queue. A new task with a TaskId collision will be discarded, and {@link + * Task#onDuplicatedTaskAdded(Task)} will be called on the existing task. + * + * @return {@code true} if the task is added, or {@code false} if the task is discarded due to + * collision. + */ + public boolean add(Task task) { + if (task.getId().id == Task.TASK_INVALID) { + throw new AssertionError("Task id was not set to a valid value before adding."); + } + if (task.getId().id != Task.TASK_ALLOW_DUPLICATES) { + Task oldTask = getTask(task.getId()); + if (oldTask != null) { + oldTask.onDuplicatedTaskAdded(task); + VvmLog.i("TaskQueue.add", "duplicated task added"); + return false; + } + } + queue.add(task); + return true; + } + + public void remove(Task task) { + queue.remove(task); + } + + public Task getTask(TaskId id) { + Assert.isMainThread(); + for (Task task : queue) { + if (task.getId().equals(id)) { + return task; + } + } + return null; + } + + /** + * Packed return value of {@link #getNextTask(long)}. If a runnable task is found {@link + * #minimalWaitTimeMillis} will be {@code null}. If no tasks is runnable {@link #task} will be + * {@code null}, and {@link #minimalWaitTimeMillis} will contain the time to wait. If there are no + * tasks at all both will be {@code null}. + */ + static final class NextTask { + @Nullable final Task task; + @Nullable final Long minimalWaitTimeMillis; + + NextTask(@Nullable Task task, @Nullable Long minimalWaitTimeMillis) { + this.task = task; + this.minimalWaitTimeMillis = minimalWaitTimeMillis; + } + } + + /** + * The next task is the first task with {@link Task#getReadyInMilliSeconds()} return a value less + * then {@code readyToleranceMillis}, in insertion order. If no task matches this criteria, the + * minimal value of {@link Task#getReadyInMilliSeconds()} is returned instead. If there are no + * tasks at all, the minimalWaitTimeMillis will also be null. + */ + @NonNull + NextTask getNextTask(long readyToleranceMillis) { + Long minimalWaitTime = null; + for (Task task : queue) { + long waitTime = task.getReadyInMilliSeconds(); + if (waitTime < readyToleranceMillis) { + return new NextTask(task, 0L); + } else { + if (minimalWaitTime == null || waitTime < minimalWaitTime) { + minimalWaitTime = waitTime; + } + } + } + return new NextTask(null, minimalWaitTime); + } + + public void clear() { + queue.clear(); + } + + public int size() { + return queue.size(); + } + + public boolean isEmpty() { + return queue.isEmpty(); + } + + @Override + public Iterator iterator() { + return queue.iterator(); + } +} diff --git a/java/com/android/voicemail/impl/scheduling/TaskReceiver.java b/java/com/android/voicemail/impl/scheduling/TaskReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..e78dcf72c571b2b1c016cf696fb649d2b264568e --- /dev/null +++ b/java/com/android/voicemail/impl/scheduling/TaskReceiver.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 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.voicemail.impl.scheduling; + +import android.annotation.TargetApi; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import com.android.voicemail.impl.VvmLog; +import java.util.ArrayList; +import java.util.List; + +/** + * BroadcastReceiver to queue and run {@link Task} with the {@link android.app.job.JobScheduler}. A + * task is queued using a explicit broadcast to this receiver. The intent should contain enough + * information in {@link Intent#getExtras()} to construct the task (see {@link + * Tasks#createIntent(Context, Class)}). The task will be queued directly in {@link TaskExecutor} if + * it is already running, or in {@link TaskSchedulerJobService} if not. + */ +@TargetApi(VERSION_CODES.O) +public class TaskReceiver extends BroadcastReceiver { + + private static final String TAG = "VvmTaskReceiver"; + + private static final List deferredBroadcasts = new ArrayList<>(); + + /** + * When {@link TaskExecutor#isTerminating()} is {@code true}, newly added tasks will be deferred + * to allow the TaskExecutor to terminate properly. After termination is completed this should be + * called to add the tasks again. + */ + public static void resendDeferredBroadcasts(Context context) { + for (Intent intent : deferredBroadcasts) { + context.sendBroadcast(intent); + } + deferredBroadcasts.clear(); + } + + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null) { + VvmLog.w(TAG, "null intent received"); + return; + } + VvmLog.i(TAG, "task received"); + TaskExecutor taskExecutor = TaskExecutor.getRunningInstance(); + if (taskExecutor != null) { + VvmLog.i(TAG, "TaskExecutor already running"); + if (taskExecutor.isTerminating()) { + // The current taskExecutor and cannot do anything and a new job cannot be scheduled. Defer + // the task until a new job can be scheduled. + VvmLog.w(TAG, "TaskExecutor is terminating, bouncing task"); + deferredBroadcasts.add(intent); + return; + } + Task task = Tasks.createTask(context.getApplicationContext(), intent.getExtras()); + taskExecutor.addTask(task); + } else { + VvmLog.i(TAG, "scheduling new job"); + List taskList = new ArrayList<>(); + taskList.add(intent.getExtras()); + TaskSchedulerJobService.scheduleJob(context.getApplicationContext(), taskList, 0, true); + } + } +} diff --git a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java new file mode 100644 index 0000000000000000000000000000000000000000..107234edc61382253f824985d56dfe133bbd1d01 --- /dev/null +++ b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2017 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.voicemail.impl.scheduling; + +import android.annotation.TargetApi; +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import android.os.Parcelable; +import android.preference.PreferenceManager; +import android.support.annotation.MainThread; +import com.android.dialer.constants.ScheduledJobIds; +import com.android.voicemail.impl.Assert; +import com.android.voicemail.impl.VvmLog; +import java.util.ArrayList; +import java.util.List; + +/** A {@link JobService} that will trigger the background execution of {@link TaskExecutor}. */ +@TargetApi(VERSION_CODES.O) +public class TaskSchedulerJobService extends JobService implements TaskExecutor.Job { + + private static final String TAG = "TaskSchedulerJobService"; + + private static final String EXTRA_TASK_EXTRAS_ARRAY = "extra_task_extras_array"; + + private static final String EXTRA_JOB_ID = "extra_job_id"; + + private static final String EXPECTED_JOB_ID = + "com.android.voicemail.impl.scheduling.TaskSchedulerJobService.EXPECTED_JOB_ID"; + + private static final String NEXT_JOB_ID = + "com.android.voicemail.impl.scheduling.TaskSchedulerJobService.NEXT_JOB_ID"; + + private JobParameters jobParameters; + + @Override + @MainThread + public boolean onStartJob(JobParameters params) { + int jobId = params.getTransientExtras().getInt(EXTRA_JOB_ID); + int expectedJobId = + PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0); + if (jobId != expectedJobId) { + VvmLog.e( + TAG, "Job " + jobId + " is not the last scheduled job " + expectedJobId + ", ignoring"); + return false; // nothing more to do. Job not running in background. + } + VvmLog.i(TAG, "starting " + jobId); + jobParameters = params; + TaskExecutor.createRunningInstance(this); + TaskExecutor.getRunningInstance() + .onStartJob( + this, + getBundleList( + jobParameters.getTransientExtras().getParcelableArray(EXTRA_TASK_EXTRAS_ARRAY))); + return true /* job still running in background */; + } + + @Override + @MainThread + public boolean onStopJob(JobParameters params) { + TaskExecutor.getRunningInstance().onStopJob(); + jobParameters = null; + return false /* don't reschedule. TaskExecutor service will post a new job */; + } + + /** + * Schedule a job to run the {@code pendingTasks}. If a job is already scheduled it will be + * appended to the back of the queue and the job will be rescheduled. A job may only be scheduled + * when the {@link TaskExecutor} is not running ({@link TaskExecutor#getRunningInstance()} + * returning {@code null}) + * + * @param delayMillis delay before running the job. Must be 0 if{@code isNewJob} is true. + * @param isNewJob a new job will be forced to run immediately. + */ + @MainThread + public static void scheduleJob( + Context context, List pendingTasks, long delayMillis, boolean isNewJob) { + Assert.isMainThread(); + JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); + JobInfo pendingJob = jobScheduler.getPendingJob(ScheduledJobIds.VVM_TASK_SCHEDULER_JOB); + VvmLog.i(TAG, "scheduling job with " + pendingTasks.size() + " tasks"); + if (pendingJob != null) { + if (isNewJob) { + List existingTasks = + getBundleList( + pendingJob.getTransientExtras().getParcelableArray(EXTRA_TASK_EXTRAS_ARRAY)); + VvmLog.i(TAG, "merging job with " + existingTasks.size() + " existing tasks"); + TaskQueue queue = new TaskQueue(); + queue.fromBundles(context, existingTasks); + for (Bundle pendingTask : pendingTasks) { + queue.add(Tasks.createTask(context, pendingTask)); + } + pendingTasks = queue.toBundles(); + } + VvmLog.i(TAG, "canceling existing job."); + jobScheduler.cancel(ScheduledJobIds.VVM_TASK_SCHEDULER_JOB); + } + Bundle extras = new Bundle(); + int jobId = createJobId(context); + extras.putInt(EXTRA_JOB_ID, jobId); + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putInt(EXPECTED_JOB_ID, jobId) + .apply(); + + extras.putParcelableArray( + EXTRA_TASK_EXTRAS_ARRAY, pendingTasks.toArray(new Bundle[pendingTasks.size()])); + JobInfo.Builder builder = + new JobInfo.Builder( + ScheduledJobIds.VVM_TASK_SCHEDULER_JOB, + new ComponentName(context, TaskSchedulerJobService.class)) + .setTransientExtras(extras) + .setMinimumLatency(delayMillis) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); + if (isNewJob) { + Assert.isTrue(delayMillis == 0); + builder.setOverrideDeadline(0); + VvmLog.i(TAG, "running job instantly."); + } + jobScheduler.schedule(builder.build()); + VvmLog.i(TAG, "job " + jobId + " scheduled"); + } + + /** + * The system will hold a wakelock when {@link #onStartJob(JobParameters)} is called to ensure the + * device will not sleep when the job is still running. Finish the job so the system will release + * the wakelock + */ + @Override + public void finishAsync() { + VvmLog.i(TAG, "finishing job"); + jobFinished(jobParameters, false); + jobParameters = null; + } + + @MainThread + @Override + public boolean isFinished() { + Assert.isMainThread(); + return getSystemService(JobScheduler.class) + .getPendingJob(ScheduledJobIds.VVM_TASK_SCHEDULER_JOB) + == null; + } + + private static List getBundleList(Parcelable[] parcelables) { + List result = new ArrayList<>(parcelables.length); + for (Parcelable parcelable : parcelables) { + result.add((Bundle) parcelable); + } + return result; + } + + private static int createJobId(Context context) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + int jobId = sharedPreferences.getInt(NEXT_JOB_ID, 0); + sharedPreferences.edit().putInt(NEXT_JOB_ID, jobId + 1).apply(); + return jobId; + } +} diff --git a/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java b/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java index 81bd36fee4d177d5cccf674fa4fc547189fa1b8f..5ad2447de51960b0b1858631f3b934706780a8e4 100644 --- a/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java +++ b/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java @@ -16,20 +16,18 @@ package com.android.voicemail.impl.scheduling; -import android.app.AlarmManager; -import android.app.PendingIntent; +import android.annotation.TargetApi; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Binder; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.PowerManager; -import android.os.PowerManager.WakeLock; -import android.os.SystemClock; import android.support.annotation.MainThread; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; @@ -37,20 +35,50 @@ import android.support.annotation.WorkerThread; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.NeededForTesting; import com.android.voicemail.impl.VvmLog; -import com.android.voicemail.impl.scheduling.Task.TaskId; -import java.util.ArrayDeque; -import java.util.Queue; +import com.android.voicemail.impl.scheduling.TaskQueue.NextTask; +import java.util.List; /** - * A service to queue and run {@link Task} on a worker thread. Only one task will be ran at a time, - * and same task cannot exist in the queue at the same time. The service will be started when a - * intent is received, and stopped when there are no more tasks in the queue. + * A service to queue and run {@link Task} with the {@link android.app.job.JobScheduler}. A task is + * queued using {@link Context#startService(Intent)}. The intent should contain enough information + * in {@link Intent#getExtras()} to construct the task (see {@link Tasks#createIntent(Context, + * Class)}). + * + *

All tasks are ran in the background with a wakelock being held by the {@link + * android.app.job.JobScheduler}, which is between {@link #onStartJob(Job, List)} and {@link + * #finishJob()}. The {@link TaskSchedulerJobService} also has a {@link TaskQueue}, but the data is + * stored in the {@link android.app.job.JobScheduler} instead of the process memory, so if the + * process is killed the queued tasks will be restored. If a new task is added, a new {@link + * TaskSchedulerJobService} will be scheduled to run the task. If the job is already scheduled, the + * new task will be pushed into the queue of the scheduled job. If the job is already running, the + * job will be queued in process memory. + * + *

Only one task will be ran at a time, and same task cannot exist in the queue at the same time. + * Refer to {@link TaskQueue} for queuing and execution order. + * + *

If there are still tasks in the queue but none are executable immediately, the service will + * enter a "sleep", pushing all remaining task into a new job and end the current job. + * + *

The service will be started when a intent is received, and stopped when there are no more + * tasks in the queue. + * + *

{@link android.app.job.JobScheduler} is not used directly due to: + * + *

    + *
  • The {@link android.telecom.PhoneAccountHandle} used to differentiate task can not be easily + * mapped into an integer for job id + *
  • A job cannot be mutated to store information such as retry count. + *
*/ +@SuppressWarnings("AndroidApiChecker") /* stream() */ +@TargetApi(VERSION_CODES.O) public class TaskSchedulerService extends Service { - private static final String TAG = "VvmTaskScheduler"; + interface Job { + void finish(); + } - private static final String ACTION_WAKEUP = "action_wakeup"; + private static final String TAG = "VvmTaskScheduler"; private static final int READY_TOLERANCE_MILLISECONDS = 100; @@ -58,15 +86,13 @@ public class TaskSchedulerService extends Service { * Threshold to determine whether to do a short or long sleep when a task is scheduled in the * future. * - *

A short sleep will continue to held the wake lock and use {@link - * Handler#postDelayed(Runnable, long)} to wait for the next task. + *

A short sleep will continue the job and use {@link Handler#postDelayed(Runnable, long)} to + * wait for the next task. * - *

A long sleep will release the wake lock and set a {@link AlarmManager} alarm. The alarm is - * exact and will wake up the device. Note: as this service is run in the telephony process it - * does not seem to be restricted by doze or sleep, it will fire exactly at the moment. The - * unbundled version should take doze into account. + *

A long sleep will finish the job and schedule a new one. The exact execution time is + * subjected to {@link android.app.job.JobScheduler} battery optimization, and is not exact. */ - private static final int SHORT_SLEEP_THRESHOLD_MILLISECONDS = 60_000; + private static final int SHORT_SLEEP_THRESHOLD_MILLISECONDS = 10_000; /** * When there are no more tasks to be run the service should be stopped. But when all tasks has * finished there might still be more tasks in the message queue waiting to be processed, @@ -75,14 +101,9 @@ public class TaskSchedulerService extends Service { */ private static final int STOP_DELAY_MILLISECONDS = 5_000; - private static final String EXTRA_CLASS_NAME = "extra_class_name"; - - private static final String WAKE_LOCK_TAG = "TaskSchedulerService_wakelock"; - // The thread to run tasks on private volatile WorkerThreadHandler mWorkerThreadHandler; - private Context mContext = this; /** * Used by tests to turn task handling into a single threaded process by calling {@link * Handler#handleMessage(Message)} directly @@ -91,21 +112,27 @@ public class TaskSchedulerService extends Service { private MainThreadHandler mMainThreadHandler; - private WakeLock mWakeLock; + // Binder given to clients + private final IBinder mBinder = new LocalBinder(); /** Main thread only, access through {@link #getTasks()} */ - private final Queue mTasks = new ArrayDeque<>(); + private final TaskQueue mTasks = new TaskQueue(); private boolean mWorkerThreadIsBusy = false; + private Job mJob; + private final Runnable mStopServiceWithDelay = new Runnable() { + @MainThread @Override public void run() { - VvmLog.d(TAG, "Stopping service"); + VvmLog.i(TAG, "Stopping service"); + finishJob(); stopSelf(); } }; + /** Should attempt to run the next task when a task has finished or been added. */ private boolean mTaskAutoRunDisabledForTesting = false; @@ -122,7 +149,7 @@ public class TaskSchedulerService extends Service { Assert.isNotMainThread(); Task task = (Task) msg.obj; try { - VvmLog.v(TAG, "executing task " + task); + VvmLog.i(TAG, "executing task " + task); task.onExecuteInBackgroundThread(); } catch (Throwable throwable) { VvmLog.e(TAG, "Exception while executing task " + task + ":", throwable); @@ -157,10 +184,6 @@ public class TaskSchedulerService extends Service { @MainThread public void onCreate() { super.onCreate(); - mWakeLock = - getSystemService(PowerManager.class) - .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG); - mWakeLock.setReferenceCounted(false); HandlerThread thread = new HandlerThread("VvmTaskSchedulerService"); thread.start(); @@ -171,27 +194,27 @@ public class TaskSchedulerService extends Service { @Override public void onDestroy() { mWorkerThreadHandler.getLooper().quit(); - mWakeLock.release(); } @Override @MainThread public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Assert.isMainThread(); - // maybeRunNextTask() will release the wakelock either by entering a long sleep or stopping - // the service. - mWakeLock.acquire(); - if (ACTION_WAKEUP.equals(intent.getAction())) { - VvmLog.d(TAG, "woke up by AlarmManager"); + if (intent == null) { + VvmLog.w(TAG, "null intent received"); + return START_NOT_STICKY; + } + Task task = Tasks.createTask(this, intent.getExtras()); + Assert.isTrue(task != null); + addTask(task); + + mMainThreadHandler.removeCallbacks(mStopServiceWithDelay); + VvmLog.i(TAG, "task added"); + if (mJob == null) { + scheduleJob(0, true); } else { - Task task = createTask(intent, flags, startId); - if (task == null) { - VvmLog.e(TAG, "cannot create task form intent"); - } else { - addTask(task); - } + maybeRunNextTask(); } - maybeRunNextTask(); // STICKY means the service will be automatically restarted will the last intent if it is // killed. return START_NOT_STICKY; @@ -201,66 +224,14 @@ public class TaskSchedulerService extends Service { @VisibleForTesting void addTask(Task task) { Assert.isMainThread(); - if (task.getId().id == Task.TASK_INVALID) { - throw new AssertionError("Task id was not set to a valid value before adding."); - } - if (task.getId().id != Task.TASK_ALLOW_DUPLICATES) { - Task oldTask = getTask(task.getId()); - if (oldTask != null) { - oldTask.onDuplicatedTaskAdded(task); - return; - } - } - mMainThreadHandler.removeCallbacks(mStopServiceWithDelay); getTasks().add(task); - maybeRunNextTask(); - } - - @MainThread - @Nullable - private Task getTask(TaskId taskId) { - Assert.isMainThread(); - for (Task task : getTasks()) { - if (task.getId().equals(taskId)) { - return task; - } - } - return null; } @MainThread - private Queue getTasks() { - Assert.isMainThread(); - return mTasks; - } - - /** Create an intent that will queue the task */ - public static Intent createIntent(Context context, Class task) { - Intent intent = new Intent(context, TaskSchedulerService.class); - intent.putExtra(EXTRA_CLASS_NAME, task.getName()); - return intent; - } - @VisibleForTesting - @MainThread - @Nullable - Task createTask(@Nullable Intent intent, int flags, int startId) { + TaskQueue getTasks() { Assert.isMainThread(); - if (intent == null) { - return null; - } - String className = intent.getStringExtra(EXTRA_CLASS_NAME); - VvmLog.d(TAG, "create task:" + className); - if (className == null) { - throw new IllegalArgumentException("EXTRA_CLASS_NAME expected"); - } - try { - Task task = (Task) Class.forName(className).newInstance(); - task.onCreate(mContext, intent, flags, startId); - return task; - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { - throw new IllegalArgumentException(e); - } + return mTasks; } @MainThread @@ -282,37 +253,31 @@ public class TaskSchedulerService extends Service { @MainThread void runNextTask() { Assert.isMainThread(); - // The current alarm is no longer valid, a new one will be set up if required. - getSystemService(AlarmManager.class).cancel(getWakeupIntent()); if (getTasks().isEmpty()) { prepareStop(); return; } - Long minimalWaitTime = null; - for (Task task : getTasks()) { - long waitTime = task.getReadyInMilliSeconds(); - if (waitTime < READY_TOLERANCE_MILLISECONDS) { - task.onBeforeExecute(); - Message message = mWorkerThreadHandler.obtainMessage(); - message.obj = task; - mWorkerThreadIsBusy = true; - mMessageSender.send(message); - return; - } else { - if (minimalWaitTime == null || waitTime < minimalWaitTime) { - minimalWaitTime = waitTime; - } - } + NextTask nextTask = getTasks().getNextTask(READY_TOLERANCE_MILLISECONDS); + + if (nextTask.task != null) { + nextTask.task.onBeforeExecute(); + Message message = mWorkerThreadHandler.obtainMessage(); + message.obj = nextTask.task; + mWorkerThreadIsBusy = true; + mMessageSender.send(message); + return; } - VvmLog.d(TAG, "minimal wait time:" + minimalWaitTime); - if (!mTaskAutoRunDisabledForTesting && minimalWaitTime != null) { + VvmLog.i(TAG, "minimal wait time:" + nextTask.minimalWaitTimeMillis); + if (!mTaskAutoRunDisabledForTesting && nextTask.minimalWaitTimeMillis != null) { // No tasks are currently ready. Sleep until the next one should be. // If a new task is added during the sleep the service will wake immediately. - sleep(minimalWaitTime); + sleep(nextTask.minimalWaitTimeMillis); } } + @MainThread private void sleep(long timeMillis) { + VvmLog.i(TAG, "sleep for " + timeMillis + " millis"); if (timeMillis < SHORT_SLEEP_THRESHOLD_MILLISECONDS) { mMainThreadHandler.postDelayed( new Runnable() { @@ -324,34 +289,24 @@ public class TaskSchedulerService extends Service { timeMillis); return; } - - // Tasks does not have a strict timing requirement, use AlarmManager.set() so the OS could - // optimize the battery usage. As this service currently run in the telephony process the - // OS give it privileges to behave the same as setExact(), but set() is the targeted - // behavior once this is unbundled. - getSystemService(AlarmManager.class) - .set( - AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + timeMillis, - getWakeupIntent()); - mWakeLock.release(); - VvmLog.d(TAG, "Long sleep for " + timeMillis + " millis"); + finishJob(); + mMainThreadHandler.post(() -> scheduleJob(timeMillis, false)); } - private PendingIntent getWakeupIntent() { - Intent intent = new Intent(ACTION_WAKEUP, null, this, getClass()); - return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + private List serializePendingTasks() { + return getTasks().toBundles(); } private void prepareStop() { - VvmLog.d( + VvmLog.i( TAG, - "No more tasks, stopping service if no task are added in " + "no more tasks, stopping service if no task are added in " + STOP_DELAY_MILLISECONDS + " millis"); mMainThreadHandler.postDelayed(mStopServiceWithDelay, STOP_DELAY_MILLISECONDS); } + @NeededForTesting static class MessageSender { public void send(Message message) { @@ -359,11 +314,6 @@ public class TaskSchedulerService extends Service { } } - @NeededForTesting - void setContextForTest(Context context) { - mContext = context; - } - @NeededForTesting void setTaskAutoRunDisabledForTest(boolean value) { mTaskAutoRunDisabledForTesting = value; @@ -374,15 +324,65 @@ public class TaskSchedulerService extends Service { mMessageSender = sender; } - @NeededForTesting - void clearTasksForTest() { + /** + * The {@link TaskSchedulerJobService} has started and all queued task should be executed in the + * worker thread. + */ + @MainThread + public void onStartJob(Job job, List pendingTasks) { + VvmLog.i(TAG, "onStartJob"); + mJob = job; + mTasks.fromBundles(this, pendingTasks); + maybeRunNextTask(); + } + + /** + * The {@link TaskSchedulerJobService} is being terminated by the system (timeout or network + * lost). A new job will be queued to resume all pending tasks. The current unfinished job may be + * ran again. + */ + @MainThread + public void onStopJob() { + VvmLog.e(TAG, "onStopJob"); + if (isJobRunning()) { + finishJob(); + mMainThreadHandler.post(() -> scheduleJob(0, true)); + } + } + + /** + * Serializes all pending tasks and schedule a new {@link TaskSchedulerJobService}. + * + * @param delayMillis the delay before stating the job, see {@link + * android.app.job.JobInfo.Builder#setMinimumLatency(long)}. This must be 0 if {@code + * isNewJob} is true. + * @param isNewJob a new job will be requested to run immediately, bypassing all requirements. + */ + @MainThread + private void scheduleJob(long delayMillis, boolean isNewJob) { + Assert.isMainThread(); + TaskSchedulerJobService.scheduleJob(this, serializePendingTasks(), delayMillis, isNewJob); mTasks.clear(); } + /** + * Signals {@link TaskSchedulerJobService} the current session of tasks has finished, and the wake + * lock can be released. Note: this only takes effect after the main thread has been returned. If + * a new job need to be scheduled, it should be posted on the main thread handler instead of + * calling directly. + */ + @MainThread + private void finishJob() { + Assert.isMainThread(); + VvmLog.i(TAG, "finishing Job"); + mJob.finish(); + mJob = null; + } + @Override @Nullable public IBinder onBind(Intent intent) { - return new LocalBinder(); + return mBinder; } @NeededForTesting @@ -393,4 +393,8 @@ public class TaskSchedulerService extends Service { return TaskSchedulerService.this; } } + + private boolean isJobRunning() { + return mJob != null; + } } diff --git a/java/com/android/voicemail/impl/scheduling/Tasks.java b/java/com/android/voicemail/impl/scheduling/Tasks.java new file mode 100644 index 0000000000000000000000000000000000000000..76da3d7f682bee211ae441a3e033d91b011f5b2d --- /dev/null +++ b/java/com/android/voicemail/impl/scheduling/Tasks.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 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.voicemail.impl.scheduling; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import com.android.voicemail.impl.VvmLog; + +/** Common operations on {@link Task} */ +final class Tasks { + + private Tasks() {} + + static final String EXTRA_CLASS_NAME = "extra_class_name"; + + /** + * Create a task from a bundle. The bundle is created either with {@link #toBundle(Task)} or + * {@link #createIntent(Context, Class)} from the target {@link Task} + */ + @NonNull + public static Task createTask(Context context, Bundle extras) { + // The extra contains custom parcelables which cannot be unmarshalled by the framework class + // loader. + extras.setClassLoader(context.getClassLoader()); + String className = extras.getString(EXTRA_CLASS_NAME); + VvmLog.i("Task.createTask", "create task:" + className); + if (className == null) { + throw new IllegalArgumentException("EXTRA_CLASS_NAME expected"); + } + try { + Task task = (Task) Class.forName(className).getDeclaredConstructor().newInstance(); + task.onCreate(context, extras); + return task; + } catch (ReflectiveOperationException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Serializes necessary states to a bundle that can be used to restore the task with {@link + * #createTask(Context, Bundle)} + */ + public static Bundle toBundle(Task task) { + Bundle result = task.toBundle(); + result.putString(EXTRA_CLASS_NAME, task.getClass().getName()); + return result; + } + + /** + * Create an intent that when called with {@link Context#startService(Intent)}, will queue the + * task. Implementations of {@link Task} should use the result of this and fill in + * necessary information. + */ + public static Intent createIntent(Context context, Class task) { + Intent intent = new Intent(context, TaskReceiver.class); + intent.setPackage(context.getPackageName()); + intent.putExtra(EXTRA_CLASS_NAME, task.getName()); + return intent; + } +} diff --git a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java index 4c95e77832def98f34bc31b06571b5c79125ce8d..9ce32a97cae85e2ef18e9fa3ebc651cb73a08b51 100644 --- a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java +++ b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java @@ -22,6 +22,7 @@ import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; import com.android.voicemail.impl.R; import com.android.voicemail.impl.VisualVoicemailPreferences; +import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.sync.VvmAccountManager; /** Save whether or not a particular account is enabled in shared to be retrieved later. */ @@ -31,6 +32,7 @@ public class VisualVoicemailSettingsUtil { public static void setEnabled( Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) { + VvmLog.i("VisualVoicemailSettingsUtil.setEnable", phoneAccount + " enabled:" + isEnabled); new VisualVoicemailPreferences(context, phoneAccount) .edit() .putBoolean(IS_ENABLED_KEY, isEnabled) diff --git a/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java b/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java index 330dc36211ef7683a0fa471cfcf29a56017774d3..b22a765cf652cef4291096dfe16352e8f89702fa 100644 --- a/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java +++ b/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java @@ -45,8 +45,7 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; -import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.DialerImpression; import com.android.voicemail.impl.OmtpConstants; import com.android.voicemail.impl.OmtpConstants.ChangePinResult; import com.android.voicemail.impl.OmtpEvents; @@ -59,6 +58,7 @@ import com.android.voicemail.impl.imap.ImapHelper; import com.android.voicemail.impl.imap.ImapHelper.InitializingException; import com.android.voicemail.impl.mail.MessagingException; import com.android.voicemail.impl.sync.VvmNetworkRequestCallback; +import com.android.voicemail.impl.utils.LoggerUtils; /** * Dialog to change the voicemail PIN. The TUI (Telephony User Interface) PIN is used when accessing @@ -278,7 +278,8 @@ public class VoicemailChangePinActivity extends Activity activity.handleOmtpEvent(OmtpEvents.CONFIG_PIN_SET); activity.finish(); - Logger.get(activity).logImpression(DialerImpression.Type.VVM_CHANGE_PIN_COMPLETED); + LoggerUtils.logImpressionOnMainThread( + activity, DialerImpression.Type.VVM_CHANGE_PIN_COMPLETED); Toast.makeText( activity, activity.getString(R.string.change_pin_succeeded), Toast.LENGTH_SHORT) .show(); diff --git a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java index 716f503ff3b938f1eb87871e63e3c0e916322a02..ac5f3cac98ea50233dc8a4bde1e7a6795fdf48b1 100644 --- a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java +++ b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java @@ -17,7 +17,6 @@ import android.annotation.TargetApi; import android.content.Intent; import android.os.Build.VERSION_CODES; import android.os.Bundle; -import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceFragment; @@ -27,8 +26,10 @@ import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; import com.android.dialer.common.Assert; +import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.notification.NotificationChannelManager; +import com.android.dialer.notification.NotificationChannelManager.Channel; import com.android.voicemail.VoicemailClient; import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; @@ -43,7 +44,6 @@ import com.android.voicemail.impl.sync.VvmAccountManager; @TargetApi(VERSION_CODES.O) public class VoicemailSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener, - VoicemailRingtonePreference.VoicemailRingtoneNameChangeListener, VvmAccountManager.Listener { private static final String TAG = "VmSettingsActivity"; @@ -51,17 +51,12 @@ public class VoicemailSettingsFragment extends PreferenceFragment @Nullable private PhoneAccountHandle phoneAccountHandle; private OmtpVvmCarrierConfigHelper omtpVvmCarrierConfigHelper; - private VoicemailRingtonePreference voicemailRingtonePreference; - private CheckBoxPreference voicemailVibration; + private Preference voicemailNotificationPreference; private SwitchPreference voicemailVisualVoicemail; private SwitchPreference autoArchiveSwitchPreference; private Preference voicemailChangePinPreference; private PreferenceScreen advancedSettings; - // The ringtone name is retrieved with an async call. Cache the old name so there will be no jank - // during transition. - private CharSequence oldRingtoneName = ""; - @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -86,12 +81,12 @@ public class VoicemailSettingsFragment extends PreferenceFragment PreferenceScreen prefSet = getPreferenceScreen(); - voicemailRingtonePreference = - (VoicemailRingtonePreference) - findPreference(getString(R.string.voicemail_notification_ringtone_key)); - voicemailRingtonePreference.setVoicemailRingtoneNameChangeListener(this); - voicemailRingtonePreference.init(phoneAccountHandle, oldRingtoneName); - voicemailRingtonePreference.setOnPreferenceClickListener( + voicemailNotificationPreference = + findPreference(getString(R.string.voicemail_notifications_key)); + voicemailNotificationPreference.setIntent( + NotificationChannelManager.getInstance() + .getSettingsIntentForChannel(getContext(), Channel.VOICEMAIL, phoneAccountHandle)); + voicemailNotificationPreference.setOnPreferenceClickListener( new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { @@ -102,24 +97,6 @@ public class VoicemailSettingsFragment extends PreferenceFragment } }); - voicemailVibration = - (CheckBoxPreference) findPreference(getString(R.string.voicemail_notification_vibrate_key)); - voicemailVibration.setOnPreferenceChangeListener(this); - voicemailVibration.setChecked( - getContext() - .getSystemService(TelephonyManager.class) - .isVoicemailVibrationEnabled(phoneAccountHandle)); - voicemailVibration.setOnPreferenceClickListener( - new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Logger.get(getContext()) - .logImpression(DialerImpression.Type.VVM_CHANGE_VIBRATION_CLICKED); - // Let the preference handle the click. - return false; - } - }); - voicemailVisualVoicemail = (SwitchPreference) findPreference(getString(R.string.voicemail_visual_voicemail_key)); @@ -164,8 +141,6 @@ public class VoicemailSettingsFragment extends PreferenceFragment VisualVoicemailSettingsUtil.isEnabled(getContext(), phoneAccountHandle)); autoArchiveSwitchPreference.setOnPreferenceChangeListener(this); - autoArchiveSwitchPreference.setSummary( - getText(R.string.voicemail_visual_voicemail_auto_archive_temporary_disclaimer)); autoArchiveSwitchPreference.setChecked( VisualVoicemailSettingsUtil.isArchiveEnabled(getContext(), phoneAccountHandle)); } else { @@ -221,10 +196,6 @@ public class VoicemailSettingsFragment extends PreferenceFragment logArchiveToggle((boolean) objValue); VisualVoicemailSettingsUtil.setArchiveEnabled( getContext(), phoneAccountHandle, (boolean) objValue); - } else if (preference.getKey().equals(voicemailVibration.getKey())) { - getContext() - .getSystemService(TelephonyManager.class) - .setVoicemailVibrationEnabled(phoneAccountHandle, (boolean) objValue); } // Always let the preference setting proceed. @@ -256,11 +227,6 @@ public class VoicemailSettingsFragment extends PreferenceFragment } } - @Override - public void onVoicemailRingtoneNameChanged(CharSequence name) { - oldRingtoneName = name; - } - @Override public void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated) { if (this.phoneAccountHandle.equals(phoneAccountHandle)) { diff --git a/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java b/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java index 1d1a639c5a340ecf22d691030ed67d7fc18b7476..5decf637650301c7425639df38292109612c6892 100644 --- a/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java +++ b/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Google Inc. All Rights Reserved. + * Copyright (C) 2016 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. @@ -16,13 +16,21 @@ package com.android.voicemail.impl.sms; +import android.annotation.TargetApi; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.support.annotation.Nullable; +import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; +import android.telephony.TelephonyManager; import android.telephony.VisualVoicemailSms; +import com.android.voicemail.VoicemailClient; import com.android.voicemail.impl.OmtpConstants; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; -import com.android.voicemail.impl.TelephonyManagerStub; import com.android.voicemail.impl.VvmLog; /** @@ -30,37 +38,95 @@ import com.android.voicemail.impl.VvmLog; * * @see OmtpVvmCarrierConfigHelper#isLegacyModeEnabled() */ +@TargetApi(VERSION_CODES.O) public class LegacyModeSmsHandler { private static final String TAG = "LegacyModeSmsHandler"; + private static final int CALL_VOICEMAIL_REQUEST_CODE = 1; + private static final int LAUNCH_VOICEMAIL_SETTINGS_REQUEST_CODE = 2; + public static void handle(Context context, VisualVoicemailSms sms) { - VvmLog.v(TAG, "processing VVM SMS on legacy mode"); + VvmLog.i(TAG, "processing VVM SMS on legacy mode"); String eventType = sms.getPrefix(); Bundle data = sms.getFields(); PhoneAccountHandle handle = sms.getPhoneAccountHandle(); if (eventType.equals(OmtpConstants.SYNC_SMS_PREFIX)) { SyncMessage message = new SyncMessage(data); - VvmLog.v( + VvmLog.i( TAG, "Received SYNC sms for " + handle + " with event " + message.getSyncTriggerEvent()); switch (message.getSyncTriggerEvent()) { case OmtpConstants.NEW_MESSAGE: case OmtpConstants.MAILBOX_UPDATE: - // The user has called into the voicemail and the new message count could - // change. - // For some carriers new message count could be set to 0 even if there are still - // unread messages, to clear the message waiting indicator. - VvmLog.v(TAG, "updating MWI"); - - // Setting voicemail message count to non-zero will show the telephony voicemail - // notification, and zero will clear it. - TelephonyManagerStub.showVoicemailNotification(message.getNewMessageCount()); + sendLegacyVoicemailNotification(context, handle, message.getNewMessageCount()); + break; default: break; } } } + + private static void sendLegacyVoicemailNotification( + Context context, PhoneAccountHandle phoneAccountHandle, int messageCount) { + // The user has called into the voicemail and the new message count could + // change. + // For some carriers new message count could be set to 0 even if there are still + // unread messages, to clear the message waiting indicator. + + VvmLog.i(TAG, "sending voicemail notification"); + Intent intent = new Intent(VoicemailClient.ACTION_SHOW_LEGACY_VOICEMAIL); + intent.setPackage(context.getPackageName()); + intent.putExtra(TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); + // Setting voicemail message count to non-zero will show the telephony voicemail + // notification, and zero will clear it. + intent.putExtra(TelephonyManager.EXTRA_NOTIFICATION_COUNT, messageCount); + + String voicemailNumber = getVoicemailNumber(context, phoneAccountHandle); + PendingIntent callVoicemailPendingIntent = null; + PendingIntent launchVoicemailSettingsPendingIntent = null; + + if (voicemailNumber != null) { + callVoicemailPendingIntent = + PendingIntent.getActivity( + context, + CALL_VOICEMAIL_REQUEST_CODE, + new Intent( + Intent.ACTION_CALL, Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null)), + PendingIntent.FLAG_UPDATE_CURRENT); + } else { + Intent launchVoicemailSettingsIntent = + new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL); + launchVoicemailSettingsIntent.putExtra(TelephonyManager.EXTRA_HIDE_PUBLIC_SETTINGS, true); + + launchVoicemailSettingsPendingIntent = + PendingIntent.getActivity( + context, + LAUNCH_VOICEMAIL_SETTINGS_REQUEST_CODE, + launchVoicemailSettingsIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + } + + intent.putExtra(TelephonyManager.EXTRA_VOICEMAIL_NUMBER, voicemailNumber); + intent.putExtra(TelephonyManager.EXTRA_CALL_VOICEMAIL_INTENT, callVoicemailPendingIntent); + intent.putExtra( + TelephonyManager.EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT, + launchVoicemailSettingsPendingIntent); + + context.sendBroadcast(intent); + } + + @Nullable + private static String getVoicemailNumber(Context context, PhoneAccountHandle phoneAccountHandle) { + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(phoneAccountHandle); + if (telephonyManager == null) { + return null; + } + return telephonyManager.getVoiceMailNumber(); + } } diff --git a/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java b/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java index 43e2b85bd8a92b56b925135f4c969813b5070033..ef0bf10e9b48ba43ff2ecc95d32566151101273b 100644 --- a/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java +++ b/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java @@ -28,7 +28,7 @@ import android.telecom.PhoneAccountHandle; import android.telephony.VisualVoicemailSms; import com.android.voicemail.impl.ActivationTask; import com.android.voicemail.impl.OmtpConstants; -import com.android.voicemail.impl.OmtpReceiver; +import com.android.voicemail.impl.OmtpService; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; import com.android.voicemail.impl.Voicemail; import com.android.voicemail.impl.Voicemail.Builder; @@ -52,7 +52,7 @@ public class OmtpMessageReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { mContext = context; - VisualVoicemailSms sms = intent.getExtras().getParcelable(OmtpReceiver.EXTRA_VOICEMAIL_SMS); + VisualVoicemailSms sms = intent.getExtras().getParcelable(OmtpService.EXTRA_VOICEMAIL_SMS); PhoneAccountHandle phone = sms.getPhoneAccountHandle(); if (phone == null) { diff --git a/java/com/android/voicemail/impl/sms/OmtpMessageSender.java b/java/com/android/voicemail/impl/sms/OmtpMessageSender.java index 6c9333fb3dfc462f32ddf60fe3181cc026853e29..e9d145cdeff84d98d704caf4f21d834aa11bc67c 100644 --- a/java/com/android/voicemail/impl/sms/OmtpMessageSender.java +++ b/java/com/android/voicemail/impl/sms/OmtpMessageSender.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Google Inc. All Rights Reserved. + * 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. @@ -20,8 +20,8 @@ import android.content.Context; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.telephony.SmsManager; -import android.telephony.VisualVoicemailService; import com.android.voicemail.impl.OmtpConstants; +import com.android.voicemail.impl.TelephonyMangerCompat; /** * Send client originated OMTP messages to the OMTP server. @@ -75,7 +75,7 @@ public abstract class OmtpMessageSender { public void requestVvmStatus(@Nullable PendingIntent sentIntent) {} protected void sendSms(String text, PendingIntent sentIntent) { - VisualVoicemailService.sendVisualVoicemailSms( + TelephonyMangerCompat.sendVisualVoicemailSms( mContext, mPhoneAccountHandle, mDestinationNumber, mApplicationPort, text, sentIntent); } diff --git a/java/com/android/voicemail/impl/sms/StatusSmsFetcher.java b/java/com/android/voicemail/impl/sms/StatusSmsFetcher.java index dd9204d3e64f3b7a4737f53afe136b88f4bcaa25..d178628c6f7e88ea9f64155a67a9a598c3186410 100644 --- a/java/com/android/voicemail/impl/sms/StatusSmsFetcher.java +++ b/java/com/android/voicemail/impl/sms/StatusSmsFetcher.java @@ -33,7 +33,7 @@ import android.telephony.SmsManager; import android.telephony.VisualVoicemailSms; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.OmtpConstants; -import com.android.voicemail.impl.OmtpReceiver; +import com.android.voicemail.impl.OmtpService; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.protocol.VisualVoicemailProtocol; @@ -67,7 +67,7 @@ public class StatusSmsFetcher extends BroadcastReceiver implements Closeable { mContext = context; mPhoneAccountHandle = phoneAccountHandle; IntentFilter filter = new IntentFilter(ACTION_REQUEST_SENT_INTENT); - filter.addAction(OmtpReceiver.ACTION_SMS_RECEIVED); + filter.addAction(OmtpService.ACTION_SMS_RECEIVED); context.registerReceiver(this, filter); } @@ -110,7 +110,7 @@ public class StatusSmsFetcher extends BroadcastReceiver implements Closeable { return; } - VisualVoicemailSms sms = intent.getExtras().getParcelable(OmtpReceiver.EXTRA_VOICEMAIL_SMS); + VisualVoicemailSms sms = intent.getExtras().getParcelable(OmtpService.EXTRA_VOICEMAIL_SMS); if (!mPhoneAccountHandle.equals(sms.getPhoneAccountHandle())) { return; diff --git a/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java b/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java index 83a3960dd7321258cbd2ef7e3621f42f1f9dfda6..3443737cdf15edce0b99bf3659a420eb6fe4f9a5 100644 --- a/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java +++ b/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java @@ -24,8 +24,7 @@ import android.support.v4.os.BuildCompat; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import android.util.ArrayMap; -import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.DialerImpression; import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.ActivationTask; import com.android.voicemail.impl.Assert; @@ -37,10 +36,12 @@ import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.fetch.VoicemailFetchedCallback; import com.android.voicemail.impl.imap.ImapHelper; import com.android.voicemail.impl.imap.ImapHelper.InitializingException; +import com.android.voicemail.impl.mail.store.ImapFolder.Quota; import com.android.voicemail.impl.scheduling.BaseTask; import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; import com.android.voicemail.impl.sync.VvmNetworkRequest.NetworkWrapper; import com.android.voicemail.impl.sync.VvmNetworkRequest.RequestFailedException; +import com.android.voicemail.impl.utils.LoggerUtils; import com.android.voicemail.impl.utils.VoicemailDatabaseUtil; import java.util.List; import java.util.Map; @@ -98,7 +99,7 @@ public class OmtpVvmSyncService { } OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(mContext, phoneAccount); - Logger.get(mContext).logImpression(DialerImpression.Type.VVM_SYNC_STARTED); + LoggerUtils.logImpressionOnMainThread(mContext, DialerImpression.Type.VVM_SYNC_STARTED); // DATA_IMAP_OPERATION_STARTED posting should not be deferred. This event clears all data // channel errors, which should happen when the task starts, not when it ends. It is the // "Sync in progress..." status. @@ -136,7 +137,7 @@ public class OmtpVvmSyncService { imapHelper.updateQuota(); autoDeleteAndArchiveVM(imapHelper, phoneAccount); imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED); - Logger.get(mContext).logImpression(DialerImpression.Type.VVM_SYNC_COMPLETED); + LoggerUtils.logImpressionOnMainThread(mContext, DialerImpression.Type.VVM_SYNC_COMPLETED); } else { task.fail(); } @@ -152,20 +153,28 @@ public class OmtpVvmSyncService { */ private void autoDeleteAndArchiveVM( ImapHelper imapHelper, PhoneAccountHandle phoneAccountHandle) { + if (!isArchiveAllowedAndEnabled(mContext, phoneAccountHandle)) { + VvmLog.i(TAG, "autoDeleteAndArchiveVM is turned off"); + LoggerUtils.logImpressionOnMainThread( + mContext, DialerImpression.Type.VVM_ARCHIVE_AUTO_DELETE_TURNED_OFF); + return; + } + Quota quotaOnServer = imapHelper.getQuota(); + if (quotaOnServer == null) { + LoggerUtils.logImpressionOnMainThread( + mContext, DialerImpression.Type.VVM_ARCHIVE_AUTO_DELETE_FAILED_DUE_TO_FAILED_QUOTA_CHECK); + VvmLog.e(TAG, "autoDeleteAndArchiveVM failed - Can't retrieve Imap quota."); + return; + } - if (isArchiveAllowedAndEnabled(mContext, phoneAccountHandle)) { - if ((float) imapHelper.getOccuupiedQuota() / (float) imapHelper.getTotalQuota() - > AUTO_DELETE_ARCHIVE_VM_THRESHOLD) { - deleteAndArchiveVM(imapHelper); - imapHelper.updateQuota(); - Logger.get(mContext) - .logImpression(DialerImpression.Type.VVM_ARCHIVE_AUTO_DELETED_VM_FROM_SERVER); - } else { - VvmLog.i(TAG, "no need to archive and auto delete VM, quota below threshold"); - } + if ((float) quotaOnServer.occupied / (float) quotaOnServer.total + > AUTO_DELETE_ARCHIVE_VM_THRESHOLD) { + deleteAndArchiveVM(imapHelper, quotaOnServer); + imapHelper.updateQuota(); + LoggerUtils.logImpressionOnMainThread( + mContext, DialerImpression.Type.VVM_ARCHIVE_AUTO_DELETED_VM_FROM_SERVER); } else { - VvmLog.i(TAG, "isArchiveAllowedAndEnabled is false"); - Logger.get(mContext).logImpression(DialerImpression.Type.VVM_ARCHIVE_AUTO_DELETE_TURNED_OFF); + VvmLog.i(TAG, "no need to archive and auto delete VM, quota below threshold"); } } @@ -189,14 +198,15 @@ public class OmtpVvmSyncService { return true; } - private void deleteAndArchiveVM(ImapHelper imapHelper) { + private void deleteAndArchiveVM(ImapHelper imapHelper, Quota quotaOnServer) { // Archive column should only be used for 0 and above Assert.isTrue(BuildCompat.isAtLeastO()); + // The number of voicemails that exceed our threshold and should be deleted from the server int numVoicemails = - imapHelper.getOccuupiedQuota() - - (int) (AUTO_DELETE_ARCHIVE_VM_THRESHOLD * imapHelper.getTotalQuota()); + quotaOnServer.occupied - (int) (AUTO_DELETE_ARCHIVE_VM_THRESHOLD * quotaOnServer.total); List oldestVoicemails = mQueryHelper.oldestVoicemailsOnServer(numVoicemails); + VvmLog.w(TAG, "number of voicemails to delete " + numVoicemails); if (!oldestVoicemails.isEmpty()) { mQueryHelper.markArchivedInDatabase(oldestVoicemails); imapHelper.markMessagesAsDeleted(oldestVoicemails); @@ -214,7 +224,7 @@ public class OmtpVvmSyncService { boolean downloadSuccess = true; if (SYNC_FULL_SYNC.equals(action) || SYNC_UPLOAD_ONLY.equals(action)) { - uploadSuccess = upload(imapHelper); + uploadSuccess = upload(account, imapHelper); } if (SYNC_FULL_SYNC.equals(action) || SYNC_DOWNLOAD_ONLY.equals(action)) { downloadSuccess = download(imapHelper, account); @@ -242,9 +252,9 @@ public class OmtpVvmSyncService { new TranscriptionFetchedCallback(mContext, voicemail), voicemail.getSourceData()); } - private boolean upload(ImapHelper imapHelper) { - List readVoicemails = mQueryHelper.getReadVoicemails(); - List deletedVoicemails = mQueryHelper.getDeletedVoicemails(); + private boolean upload(PhoneAccountHandle phoneAccountHandle, ImapHelper imapHelper) { + List readVoicemails = mQueryHelper.getReadVoicemails(phoneAccountHandle); + List deletedVoicemails = mQueryHelper.getDeletedVoicemails(phoneAccountHandle); boolean success = true; @@ -271,7 +281,7 @@ public class OmtpVvmSyncService { private boolean download(ImapHelper imapHelper, PhoneAccountHandle account) { List serverVoicemails = imapHelper.fetchAllVoicemails(); - List localVoicemails = mQueryHelper.getAllVoicemails(); + List localVoicemails = mQueryHelper.getAllVoicemails(account); if (localVoicemails == null || serverVoicemails == null) { // Null value means the query failed. @@ -302,7 +312,8 @@ public class OmtpVvmSyncService { if (!TextUtils.isEmpty(remoteVoicemail.getTranscription()) && TextUtils.isEmpty(localVoicemail.getTranscription())) { - Logger.get(mContext).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_DOWNLOADED); + LoggerUtils.logImpressionOnMainThread( + mContext, DialerImpression.Type.VVM_TRANSCRIPTION_DOWNLOADED); mQueryHelper.updateWithTranscription(localVoicemail, remoteVoicemail.getTranscription()); } } @@ -312,7 +323,8 @@ public class OmtpVvmSyncService { boolean prefetchEnabled = shouldPerformPrefetch(account, imapHelper); for (Voicemail remoteVoicemail : remoteMap.values()) { if (!TextUtils.isEmpty(remoteVoicemail.getTranscription())) { - Logger.get(mContext).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_DOWNLOADED); + LoggerUtils.logImpressionOnMainThread( + mContext, DialerImpression.Type.VVM_TRANSCRIPTION_DOWNLOADED); } Uri uri = VoicemailDatabaseUtil.insert(mContext, remoteVoicemail); if (prefetchEnabled) { diff --git a/java/com/android/voicemail/impl/sync/SyncOneTask.java b/java/com/android/voicemail/impl/sync/SyncOneTask.java index e57235e4b806144a7ec7988185dec39b38e0a6fa..cd2782abbf9fddefee70da8f74a5b409bf6e8793 100644 --- a/java/com/android/voicemail/impl/sync/SyncOneTask.java +++ b/java/com/android/voicemail/impl/sync/SyncOneTask.java @@ -18,18 +18,21 @@ package com.android.voicemail.impl.sync; import android.content.Context; import android.content.Intent; +import android.os.Bundle; import android.telecom.PhoneAccountHandle; -import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.proguard.UsedByReflection; import com.android.voicemail.impl.Voicemail; import com.android.voicemail.impl.VoicemailStatus; import com.android.voicemail.impl.scheduling.BaseTask; import com.android.voicemail.impl.scheduling.RetryPolicy; +import com.android.voicemail.impl.utils.LoggerUtils; /** * Task to download a single voicemail from the server. This task is initiated by a SMS notifying * the new voicemail arrival, and ignores the duplicated tasks constraint. */ +@UsedByReflection(value = "Tasks.java") public class SyncOneTask extends BaseTask { private static final int RETRY_TIMES = 2; @@ -48,7 +51,7 @@ public class SyncOneTask extends BaseTask { intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone); intent.putExtra(EXTRA_SYNC_TYPE, OmtpVvmSyncService.SYNC_DOWNLOAD_ONE_TRANSCRIPTION); intent.putExtra(EXTRA_VOICEMAIL, voicemail); - context.startService(intent); + context.sendBroadcast(intent); } public SyncOneTask() { @@ -56,11 +59,12 @@ public class SyncOneTask extends BaseTask { addPolicy(new RetryPolicy(RETRY_TIMES, RETRY_INTERVAL_MILLIS)); } - public void onCreate(Context context, Intent intent, int flags, int startId) { - super.onCreate(context, intent, flags, startId); - mPhone = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE); - mSyncType = intent.getStringExtra(EXTRA_SYNC_TYPE); - mVoicemail = intent.getParcelableExtra(EXTRA_VOICEMAIL); + @Override + public void onCreate(Context context, Bundle extras) { + super.onCreate(context, extras); + mPhone = extras.getParcelable(EXTRA_PHONE_ACCOUNT_HANDLE); + mSyncType = extras.getString(EXTRA_SYNC_TYPE); + mVoicemail = extras.getParcelable(EXTRA_VOICEMAIL); } @Override @@ -71,7 +75,7 @@ public class SyncOneTask extends BaseTask { @Override public Intent createRestartIntent() { - Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_AUTO_RETRY_SYNC); + LoggerUtils.logImpressionOnMainThread(getContext(), DialerImpression.Type.VVM_AUTO_RETRY_SYNC); Intent intent = super.createRestartIntent(); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, mPhone); intent.putExtra(EXTRA_SYNC_TYPE, mSyncType); diff --git a/java/com/android/voicemail/impl/sync/SyncTask.java b/java/com/android/voicemail/impl/sync/SyncTask.java index a9e5920688253aee5b7890a3a8040c070e3b63ac..0b3e090bf694688b2625a8865fc7f28dac8e9665 100644 --- a/java/com/android/voicemail/impl/sync/SyncTask.java +++ b/java/com/android/voicemail/impl/sync/SyncTask.java @@ -18,14 +18,17 @@ package com.android.voicemail.impl.sync; import android.content.Context; import android.content.Intent; +import android.os.Bundle; import android.telecom.PhoneAccountHandle; -import com.android.dialer.logging.Logger; -import com.android.dialer.logging.nano.DialerImpression; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.proguard.UsedByReflection; import com.android.voicemail.impl.scheduling.BaseTask; import com.android.voicemail.impl.scheduling.MinimalIntervalPolicy; import com.android.voicemail.impl.scheduling.RetryPolicy; +import com.android.voicemail.impl.utils.LoggerUtils; /** System initiated sync request. */ +@UsedByReflection(value = "Tasks.java") public class SyncTask extends BaseTask { // Try sync for a total of 5 times, should take around 5 minutes before finally giving up. @@ -45,7 +48,7 @@ public class SyncTask extends BaseTask { Intent intent = BaseTask.createIntent(context, SyncTask.class, phone); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone); intent.putExtra(EXTRA_SYNC_TYPE, syncType); - context.startService(intent); + context.sendBroadcast(intent); } public SyncTask() { @@ -55,10 +58,11 @@ public class SyncTask extends BaseTask { addPolicy(new MinimalIntervalPolicy(MINIMAL_INTERVAL_MILLIS)); } - public void onCreate(Context context, Intent intent, int flags, int startId) { - super.onCreate(context, intent, flags, startId); - mPhone = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE); - mSyncType = intent.getStringExtra(EXTRA_SYNC_TYPE); + @Override + public void onCreate(Context context, Bundle extras) { + super.onCreate(context, extras); + mPhone = extras.getParcelable(EXTRA_PHONE_ACCOUNT_HANDLE); + mSyncType = extras.getString(EXTRA_SYNC_TYPE); } @Override @@ -69,7 +73,7 @@ public class SyncTask extends BaseTask { @Override public Intent createRestartIntent() { - Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_AUTO_RETRY_SYNC); + LoggerUtils.logImpressionOnMainThread(getContext(), DialerImpression.Type.VVM_AUTO_RETRY_SYNC); Intent intent = super.createRestartIntent(); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, mPhone); intent.putExtra(EXTRA_SYNC_TYPE, mSyncType); diff --git a/java/com/android/voicemail/impl/sync/UploadTask.java b/java/com/android/voicemail/impl/sync/UploadTask.java index 7d1a79756807f24eed21c9e3efdabb6d5b62ac80..f2b2036b54b09c6c5c1da840ec36faf9a1088330 100644 --- a/java/com/android/voicemail/impl/sync/UploadTask.java +++ b/java/com/android/voicemail/impl/sync/UploadTask.java @@ -18,7 +18,9 @@ package com.android.voicemail.impl.sync; import android.content.Context; import android.content.Intent; +import android.os.Bundle; import android.telecom.PhoneAccountHandle; +import com.android.dialer.proguard.UsedByReflection; import com.android.voicemail.impl.VoicemailStatus; import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.scheduling.BaseTask; @@ -28,6 +30,7 @@ import com.android.voicemail.impl.scheduling.PostponePolicy; * Upload task triggered by database changes. Will wait until the database has been stable for * {@link #POSTPONE_MILLIS} to execute. */ +@UsedByReflection(value = "Tasks.java") public class UploadTask extends BaseTask { private static final String TAG = "VvmUploadTask"; @@ -41,12 +44,12 @@ public class UploadTask extends BaseTask { public static void start(Context context, PhoneAccountHandle phoneAccountHandle) { Intent intent = BaseTask.createIntent(context, UploadTask.class, phoneAccountHandle); - context.startService(intent); + context.sendBroadcast(intent); } @Override - public void onCreate(Context context, Intent intent, int flags, int startId) { - super.onCreate(context, intent, flags, startId); + public void onCreate(Context context, Bundle extras) { + super.onCreate(context, extras); } @Override diff --git a/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java b/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java index fc8119a80b89972a36ab7e2c16215feab8c16057..9b295dbb7feca4fac2ed971dc30d5f945637b7f0 100644 --- a/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java +++ b/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java @@ -25,6 +25,7 @@ import android.net.Uri; import android.os.Build.VERSION_CODES; import android.provider.VoicemailContract; import android.provider.VoicemailContract.Voicemails; +import android.support.annotation.NonNull; import android.telecom.PhoneAccountHandle; import com.android.dialer.common.Assert; import com.android.voicemail.impl.Voicemail; @@ -68,8 +69,8 @@ public class VoicemailsQueryHelper { * * @return A list of read voicemails. */ - public List getReadVoicemails() { - return getLocalVoicemails(READ_SELECTION); + public List getReadVoicemails(@NonNull PhoneAccountHandle phoneAccountHandle) { + return getLocalVoicemails(phoneAccountHandle, READ_SELECTION); } /** @@ -77,8 +78,8 @@ public class VoicemailsQueryHelper { * * @return A list of deleted voicemails. */ - public List getDeletedVoicemails() { - return getLocalVoicemails(DELETED_SELECTION); + public List getDeletedVoicemails(@NonNull PhoneAccountHandle phoneAccountHandle) { + return getLocalVoicemails(phoneAccountHandle, DELETED_SELECTION); } /** @@ -86,17 +87,20 @@ public class VoicemailsQueryHelper { * * @return A list of all locally stored voicemails. */ - public List getAllVoicemails() { - return getLocalVoicemails(null); + public List getAllVoicemails(@NonNull PhoneAccountHandle phoneAccountHandle) { + return getLocalVoicemails(phoneAccountHandle, null); } /** * Utility method to make queries to the voicemail database. * + *

TODO(b/36588206) add PhoneAccountHandle filtering back + * * @param selection A filter declaring which rows to return. {@code null} returns all rows. * @return A list of voicemails according to the selection statement. */ - private List getLocalVoicemails(String selection) { + private List getLocalVoicemails( + @NonNull PhoneAccountHandle unusedPhoneAccountHandle, String selection) { Cursor cursor = mContentResolver.query(mSourceUri, PROJECTION, selection, null, null); if (cursor == null) { return null; diff --git a/java/com/android/voicemail/impl/utils/LoggerUtils.java b/java/com/android/voicemail/impl/utils/LoggerUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..070772f2fdca9667f858e043b34b11eb6174fdb4 --- /dev/null +++ b/java/com/android/voicemail/impl/utils/LoggerUtils.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 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.voicemail.impl.utils; + +import android.content.Context; +import android.support.annotation.AnyThread; +import com.android.dialer.common.concurrent.ThreadUtil; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; + +/** Common utility method when using {@link Logger} */ +public class LoggerUtils { + + /** Posts the impression logging to the main thread so it will be thread safe. */ + @AnyThread + public static void logImpressionOnMainThread(Context context, DialerImpression.Type impression) { + ThreadUtil.postOnUiThread(() -> Logger.get(context).logImpression(impression)); + } +} diff --git a/java/com/android/voicemail/permissions.xml b/java/com/android/voicemail/permissions.xml index adb4b6f54e79a0d29fb9e40056eeea9afdd1c783..bedf0689850decbfcbc24fa83827792bfe6edb97 100644 --- a/java/com/android/voicemail/permissions.xml +++ b/java/com/android/voicemail/permissions.xml @@ -3,7 +3,7 @@ + android:targetSdkVersion="26"/> diff --git a/java/com/android/voicemail/stub/StubVoicemailClient.java b/java/com/android/voicemail/stub/StubVoicemailClient.java index 172b3ffcc51f321666fe57bc095a8e89e692f1f8..e2b47079997c498cbaa4288e76f7e7de13466388 100644 --- a/java/com/android/voicemail/stub/StubVoicemailClient.java +++ b/java/com/android/voicemail/stub/StubVoicemailClient.java @@ -36,6 +36,15 @@ public final class StubVoicemailClient implements VoicemailClient { return false; } + @Override + public boolean isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle) { + return false; + } + + @Override + public void setVoicemailEnabled( + Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {} + @Override public void appendOmtpVoicemailSelectionClause( Context context, StringBuilder where, List selectionArgs) {} @@ -67,4 +76,9 @@ public final class StubVoicemailClient implements VoicemailClient { public Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle) { return new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL); } + + @Override + public boolean isActivated(Context context, PhoneAccountHandle phoneAccountHandle) { + return false; + } }