summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/FragmentManager.java16
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java10
-rw-r--r--core/java/android/app/assist/AssistStructure.java20
-rw-r--r--core/java/android/app/backup/BackupManagerMonitor.java16
-rw-r--r--core/java/android/app/usage/CacheQuotaHint.aidl20
-rw-r--r--core/java/android/app/usage/CacheQuotaHint.java142
-rw-r--r--core/java/android/app/usage/CacheQuotaService.java112
-rw-r--r--core/java/android/app/usage/ICacheQuotaService.aidl25
-rw-r--r--core/java/android/app/usage/IStorageStatsManager.aidl1
-rw-r--r--core/java/android/app/usage/StorageStatsManager.java9
-rw-r--r--core/java/android/app/usage/UsageStatsManagerInternal.java5
-rw-r--r--core/java/android/content/Intent.java22
-rw-r--r--core/java/android/inputmethodservice/KeyboardView.java68
-rw-r--r--core/java/android/net/ConnectivityManager.java161
-rw-r--r--core/java/android/os/FileUtils.java7
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java19
-rw-r--r--core/java/android/os/storage/IStorageManager.aidl4
-rw-r--r--core/java/android/os/storage/StorageManager.java200
-rwxr-xr-xcore/java/android/provider/Settings.java35
-rw-r--r--core/java/android/service/autofill/Dataset.java18
-rw-r--r--core/java/android/service/autofill/FillResponse.java81
-rw-r--r--core/java/android/text/SpannableStringInternal.java47
-rw-r--r--core/java/android/view/IGraphicsStats.aidl3
-rw-r--r--core/java/android/view/IGraphicsStatsCallback.aidl24
-rw-r--r--core/java/android/view/ThreadedRenderer.java80
-rw-r--r--core/java/android/view/View.java12
-rw-r--r--core/java/android/view/ViewConfiguration.java5
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/java/android/view/ViewStructure.java29
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java3
-rw-r--r--core/java/android/view/autofill/AutoFillManager.java6
-rw-r--r--core/java/android/widget/CompoundButton.java9
-rw-r--r--core/java/android/widget/DayPickerView.java7
-rw-r--r--core/java/android/widget/RadioGroup.java7
-rw-r--r--core/java/android/widget/TextView.java81
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java15
36 files changed, 919 insertions, 404 deletions
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 739015fd2e65..8ad7810a13e8 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2807,40 +2807,56 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
public void dispatchCreate() {
mStateSaved = false;
+ mExecutingActions = true;
moveToState(Fragment.CREATED, false);
+ mExecutingActions = false;
}
public void dispatchActivityCreated() {
mStateSaved = false;
+ mExecutingActions = true;
moveToState(Fragment.ACTIVITY_CREATED, false);
+ mExecutingActions = false;
}
public void dispatchStart() {
mStateSaved = false;
+ mExecutingActions = true;
moveToState(Fragment.STARTED, false);
+ mExecutingActions = false;
}
public void dispatchResume() {
mStateSaved = false;
+ mExecutingActions = true;
moveToState(Fragment.RESUMED, false);
+ mExecutingActions = false;
}
public void dispatchPause() {
+ mExecutingActions = true;
moveToState(Fragment.STARTED, false);
+ mExecutingActions = false;
}
public void dispatchStop() {
+ mExecutingActions = true;
moveToState(Fragment.STOPPED, false);
+ mExecutingActions = false;
}
public void dispatchDestroyView() {
+ mExecutingActions = true;
moveToState(Fragment.CREATED, false);
+ mExecutingActions = false;
}
public void dispatchDestroy() {
mDestroyed = true;
execPendingActions();
+ mExecutingActions = true;
moveToState(Fragment.INITIALIZING, false);
+ mExecutingActions = false;
mHost = null;
mContainer = null;
mParent = null;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2ace0a211dd6..9cb3dd6e4c0a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6343,7 +6343,6 @@ public class DevicePolicyManager {
* The settings that can be updated by a profile or device owner with this method are:
* <ul>
* <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li>
- * <li>{@link Settings.Secure#INSTALL_NON_MARKET_APPS}</li>
* <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li>
* </ul>
* <p>
@@ -6352,6 +6351,15 @@ public class DevicePolicyManager {
* <li>{@link Settings.Secure#LOCATION_MODE}</li>
* </ul>
*
+ * <strong>Note: Starting from Android O, apps should no longer call this method with the
+ * setting {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS}, which is
+ * deprecated. Instead, device owners or profile owners should use the restriction
+ * {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}.
+ * If any app targeting {@link android.os.Build.VERSION_CODES#O} or higher calls this method
+ * with {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS},
+ * an {@link UnsupportedOperationException} is thrown.
+ * </strong>
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param setting The name of the setting to update.
* @param value The value to update the setting to.
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 8d385db263df..678c017febe0 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -419,7 +419,7 @@ public class AssistStructure implements Parcelable {
mDisplayId = root.getDisplayId();
mRoot = new ViewNode();
- ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false, 0);
+ ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
if (forAutoFill) {
// NOTE: flags are currently not supported, hence 0
@@ -1059,6 +1059,10 @@ public class AssistStructure implements Parcelable {
* <li>Root node (containing the URL of the HTML page)
* <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
* </ol>
+ *
+ * <strong>WARNING:</strong> a {@link android.service.autofill.AutoFillService} should only
+ * use this URL for auto-fill purposes when it trusts the app generating it (i.e., the app
+ * defined by {@link AssistStructure#getActivityComponent()}).
*/
public String getUrl() {
return mUrl;
@@ -1187,11 +1191,10 @@ public class AssistStructure implements Parcelable {
final ViewNode mNode;
final boolean mAsync;
- ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async, int flags) {
+ ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
mAssist = assist;
mNode = node;
mAsync = async;
- mNode.mSanitized = (flags & AUTO_FILL_FLAG_SANITIZED) != 0;
}
@Override
@@ -1429,16 +1432,15 @@ public class AssistStructure implements Parcelable {
ViewNode node = new ViewNode();
setAutoFillId(node, forAutoFill, virtualId);
mNode.mChildren[index] = node;
- return new ViewNodeBuilder(mAssist, node, false, flags);
+ return new ViewNodeBuilder(mAssist, node, false);
}
- private ViewStructure asyncNewChild(int index, boolean forAutoFill, int virtualId,
- int flags) {
+ private ViewStructure asyncNewChild(int index, boolean forAutoFill, int virtualId) {
synchronized (mAssist) {
ViewNode node = new ViewNode();
setAutoFillId(node, forAutoFill, virtualId);
mNode.mChildren[index] = node;
- ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true, flags);
+ ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
mAssist.mPendingAsyncChildren.add(builder);
return builder;
}
@@ -1457,12 +1459,12 @@ public class AssistStructure implements Parcelable {
@Override
public ViewStructure asyncNewChild(int index) {
- return asyncNewChild(index, false, 0, 0);
+ return asyncNewChild(index, false, 0);
}
@Override
public ViewStructure asyncNewChild(int index, int virtualId, int flags) {
- return asyncNewChild(index, true, virtualId, flags);
+ return asyncNewChild(index, true, virtualId);
}
@Override
diff --git a/core/java/android/app/backup/BackupManagerMonitor.java b/core/java/android/app/backup/BackupManagerMonitor.java
index 099878b310c5..d2a623e0b13a 100644
--- a/core/java/android/app/backup/BackupManagerMonitor.java
+++ b/core/java/android/app/backup/BackupManagerMonitor.java
@@ -54,15 +54,31 @@ public class BackupManagerMonitor {
public static final String EXTRA_LOG_EVENT_CATEGORY =
"android.app.backup.extra.LOG_EVENT_CATEGORY";
+ /**
+ * string: when we have event of id LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER we send the version
+ * of the backup.
+ */
+ public static final String EXTRA_LOG_OLD_VERSION =
+ "android.app.backup.extra.LOG_OLD_VERSION";
+
// TODO complete this list with all log messages. And document properly.
public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4;
+ public static final int LOG_EVENT_ID_PACKAGE_NOT_FOUND = 12;
+ public static final int LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT = 15;
public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21;
+ public static final int LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE = 22;
+ public static final int LOG_EVENT_ID_PACKAGE_NOT_PRESENT = 26;
+ public static final int LOG_EVENT_ID_APP_HAS_NO_AGENT = 28;
+ public static final int LOG_EVENT_ID_CANT_FIND_AGENT = 30;
public static final int LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT = 31;
+ public static final int LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER = 36;
public static final int LOG_EVENT_ID_FULL_RESTORE_TIMEOUT = 45;
public static final int LOG_EVENT_ID_NO_PACKAGES = 49;
+
+
/**
* This method will be called each time something important happens on BackupManager.
*
diff --git a/core/java/android/app/usage/CacheQuotaHint.aidl b/core/java/android/app/usage/CacheQuotaHint.aidl
new file mode 100644
index 000000000000..0470ea730b65
--- /dev/null
+++ b/core/java/android/app/usage/CacheQuotaHint.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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 android.app.usage;
+
+/** {@hide} */
+parcelable CacheQuotaHint; \ No newline at end of file
diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java
new file mode 100644
index 000000000000..4b6f99b43a09
--- /dev/null
+++ b/core/java/android/app/usage/CacheQuotaHint.java
@@ -0,0 +1,142 @@
+/*
+ * 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 android.app.usage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * CacheQuotaRequest represents a triplet of a uid, the volume UUID it is stored upon, and
+ * its usage stats. When processed, it obtains a cache quota as defined by the system which
+ * allows apps to understand how much cache to use.
+ * {@hide}
+ */
+@SystemApi
+public final class CacheQuotaHint implements Parcelable {
+ public static final long QUOTA_NOT_SET = -1;
+ private final String mUuid;
+ private final int mUid;
+ private final UsageStats mUsageStats;
+ private final long mQuota;
+
+ /**
+ * Create a new request.
+ * @param builder A builder for this object.
+ */
+ public CacheQuotaHint(Builder builder) {
+ this.mUuid = builder.mUuid;
+ this.mUid = builder.mUid;
+ this.mUsageStats = builder.mUsageStats;
+ this.mQuota = builder.mQuota;
+ }
+
+ public String getVolumeUuid() {
+ return mUuid;
+ }
+
+ public int getUid() {
+ return mUid;
+ }
+
+ public long getQuota() {
+ return mQuota;
+ }
+
+ public UsageStats getUsageStats() {
+ return mUsageStats;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mUuid);
+ dest.writeInt(mUid);
+ dest.writeLong(mQuota);
+ dest.writeParcelable(mUsageStats, 0);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final class Builder {
+ private String mUuid;
+ private int mUid;
+ private UsageStats mUsageStats;
+ private long mQuota;
+
+ public Builder() {
+ }
+
+ public Builder(CacheQuotaHint hint) {
+ setVolumeUuid(hint.getVolumeUuid());
+ setUid(hint.getUid());
+ setUsageStats(hint.getUsageStats());
+ setQuota(hint.getQuota());
+ }
+
+ public @NonNull Builder setVolumeUuid(@Nullable String uuid) {
+ mUuid = uuid;
+ return this;
+ }
+
+ public @NonNull Builder setUid(int uid) {
+ Preconditions.checkArgumentPositive(uid, "Proposed uid was not positive.");
+ mUid = uid;
+ return this;
+ }
+
+ public @NonNull Builder setUsageStats(@Nullable UsageStats stats) {
+ mUsageStats = stats;
+ return this;
+ }
+
+ public @NonNull Builder setQuota(long quota) {
+ Preconditions.checkArgument((quota >= QUOTA_NOT_SET));
+ mQuota = quota;
+ return this;
+ }
+
+ public @NonNull CacheQuotaHint build() {
+ Preconditions.checkNotNull(mUsageStats);
+ return new CacheQuotaHint(this);
+ }
+ }
+
+ public static final Parcelable.Creator<CacheQuotaHint> CREATOR =
+ new Creator<CacheQuotaHint>() {
+ @Override
+ public CacheQuotaHint createFromParcel(Parcel in) {
+ final Builder builder = new Builder();
+ return builder.setVolumeUuid(in.readString())
+ .setUid(in.readInt())
+ .setQuota(in.readLong())
+ .setUsageStats(in.readParcelable(UsageStats.class.getClassLoader()))
+ .build();
+ }
+
+ @Override
+ public CacheQuotaHint[] newArray(int size) {
+ return new CacheQuotaHint[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/CacheQuotaService.java b/core/java/android/app/usage/CacheQuotaService.java
new file mode 100644
index 000000000000..b9430ab97e06
--- /dev/null
+++ b/core/java/android/app/usage/CacheQuotaService.java
@@ -0,0 +1,112 @@
+/*
+ * 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 android.app.usage;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.app.usage.ICacheQuotaService;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallback;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * CacheQuoteService defines a service which accepts cache quota requests and processes them,
+ * thereby filling out how much quota each request deserves.
+ * {@hide}
+ */
+@SystemApi
+public abstract class CacheQuotaService extends Service {
+ private static final String TAG = "CacheQuotaService";
+
+ /**
+ * The {@link Intent} action that must be declared as handled by a service
+ * in its manifest for the system to recognize it as a quota providing service.
+ */
+ public static final String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService";
+
+ /** {@hide} **/
+ public static final String REQUEST_LIST_KEY = "requests";
+
+ private CacheQuotaServiceWrapper mWrapper;
+ private Handler mHandler;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWrapper = new CacheQuotaServiceWrapper();
+ mHandler = new ServiceHandler(getMainLooper());
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mWrapper;
+ }
+
+ /**
+ * Processes the cache quota list upon receiving a list of requests.
+ * @param requests A list of cache quotas to fulfill.
+ * @return A completed list of cache quota requests.
+ */
+ public abstract List<CacheQuotaHint> onComputeCacheQuotaHints(
+ List<CacheQuotaHint> requests);
+
+ private final class CacheQuotaServiceWrapper extends ICacheQuotaService.Stub {
+ @Override
+ public void computeCacheQuotaHints(
+ RemoteCallback callback, List<CacheQuotaHint> requests) {
+ final Pair<RemoteCallback, List<CacheQuotaHint>> pair =
+ Pair.create(callback, requests);
+ Message msg = mHandler.obtainMessage(ServiceHandler.MSG_SEND_LIST, pair);
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ private final class ServiceHandler extends Handler {
+ public static final int MSG_SEND_LIST = 1;
+
+ public ServiceHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final int action = msg.what;
+ switch (action) {
+ case MSG_SEND_LIST:
+ final Pair<RemoteCallback, List<CacheQuotaHint>> pair =
+ (Pair<RemoteCallback, List<CacheQuotaHint>>) msg.obj;
+ List<CacheQuotaHint> processed = onComputeCacheQuotaHints(pair.second);
+ final Bundle data = new Bundle();
+ data.putParcelableList(REQUEST_LIST_KEY, processed);
+
+ final RemoteCallback callback = pair.first;
+ callback.sendResult(data);
+ break;
+ default:
+ Log.w(TAG, "Handling unknown message: " + action);
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/usage/ICacheQuotaService.aidl b/core/java/android/app/usage/ICacheQuotaService.aidl
new file mode 100644
index 000000000000..8d984e0bf7b4
--- /dev/null
+++ b/core/java/android/app/usage/ICacheQuotaService.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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 android.app.usage;
+
+import android.os.RemoteCallback;
+import android.app.usage.CacheQuotaHint;
+
+/** {@hide} */
+oneway interface ICacheQuotaService {
+ void computeCacheQuotaHints(in RemoteCallback callback, in List<CacheQuotaHint> requests);
+}
diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl
index 62ebf6085aba..f4c18dda5160 100644
--- a/core/java/android/app/usage/IStorageStatsManager.aidl
+++ b/core/java/android/app/usage/IStorageStatsManager.aidl
@@ -21,6 +21,7 @@ import android.app.usage.ExternalStorageStats;
/** {@hide} */
interface IStorageStatsManager {
+ boolean isQuotaSupported(String volumeUuid, String callingPackage);
long getTotalBytes(String volumeUuid, String callingPackage);
long getFreeBytes(String volumeUuid, String callingPackage);
StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage);
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 9d30771aaeba..7d4efb9c108b 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -46,6 +46,15 @@ public class StorageStatsManager {
mService = Preconditions.checkNotNull(service);
}
+ /** {@hide} */
+ public boolean isQuotaSupported(String volumeUuid) {
+ try {
+ return mService.isQuotaSupported(volumeUuid, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Return the total space on the requested storage volume.
* <p>
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index a6f91fe17227..08595dd1b3b4 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -19,7 +19,7 @@ package android.app.usage;
import android.content.ComponentName;
import android.content.res.Configuration;
-import java.io.IOException;
+import java.util.List;
/**
* UsageStatsManager local system service interface.
@@ -127,4 +127,7 @@ public abstract class UsageStatsManagerInternal {
public abstract void applyRestoredPayload(int user, String key, byte[] payload);
+ /* Cache Quota Service API */
+ public abstract List<UsageStats> queryUsageStatsForUser(
+ int userId, int interval, long beginTime, long endTime);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b0505ac4a3a2..28068c54744c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2873,6 +2873,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @hide
*/
+ @SystemApi
public static final String ACTION_PRE_BOOT_COMPLETED =
"android.intent.action.PRE_BOOT_COMPLETED";
@@ -3313,6 +3314,16 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
/**
+ * Broadcast intent sent by the RecoverySystem to inform listeners that a master clear (wipe)
+ * is about to be performed.
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MASTER_CLEAR_NOTIFICATION
+ = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
+
+ /**
* Boolean intent extra to be used with {@link #ACTION_MASTER_CLEAR} in order to force a factory
* reset even if {@link android.os.UserManager#DISALLOW_FACTORY_RESET} is set.
*
@@ -3384,6 +3395,17 @@ public class Intent implements Parcelable, Cloneable {
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
+
+ /**
+ * Broadcast Action: The sim card state has changed.
+ * For more details see TelephonyIntents.ACTION_SIM_STATE_CHANGED. This is here
+ * because TelephonyIntents is an internal class.
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
+
/**
* The name of the extra used to define the text to be processed, as a
* CharSequence. Note that this may be a styled CharSequence, so you must use
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index d1000ade1ed0..13b9206b12ee 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -988,49 +988,31 @@ public class KeyboardView extends View implements View.OnClickListener {
if (mAccessibilityManager.isEnabled()) {
AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
onInitializeAccessibilityEvent(event);
- String text = null;
- // This is very efficient since the properties are cached.
- final boolean speakPassword = Settings.Secure.getIntForUser(
- mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
- UserHandle.USER_CURRENT_OR_SELF) != 0;
- // Add text only if password announcement is enabled or if headset is
- // used to avoid leaking passwords.
- if (speakPassword || mAudioManager.isBluetoothA2dpOn()
- || mAudioManager.isWiredHeadsetOn()) {
- switch (code) {
- case Keyboard.KEYCODE_ALT:
- text = mContext.getString(R.string.keyboardview_keycode_alt);
- break;
- case Keyboard.KEYCODE_CANCEL:
- text = mContext.getString(R.string.keyboardview_keycode_cancel);
- break;
- case Keyboard.KEYCODE_DELETE:
- text = mContext.getString(R.string.keyboardview_keycode_delete);
- break;
- case Keyboard.KEYCODE_DONE:
- text = mContext.getString(R.string.keyboardview_keycode_done);
- break;
- case Keyboard.KEYCODE_MODE_CHANGE:
- text = mContext.getString(R.string.keyboardview_keycode_mode_change);
- break;
- case Keyboard.KEYCODE_SHIFT:
- text = mContext.getString(R.string.keyboardview_keycode_shift);
- break;
- case '\n':
- text = mContext.getString(R.string.keyboardview_keycode_enter);
- break;
- default:
- text = String.valueOf((char) code);
- }
- } else if (!mHeadsetRequiredToHearPasswordsAnnounced) {
- // We want the waring for required head set to be send with both the
- // hover enter and hover exit event, so set the flag after the exit.
- if (eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mHeadsetRequiredToHearPasswordsAnnounced = true;
- }
- text = mContext.getString(R.string.keyboard_headset_required_to_hear_password);
- } else {
- text = mContext.getString(R.string.keyboard_password_character_no_headset);
+ final String text;
+ switch (code) {
+ case Keyboard.KEYCODE_ALT:
+ text = mContext.getString(R.string.keyboardview_keycode_alt);
+ break;
+ case Keyboard.KEYCODE_CANCEL:
+ text = mContext.getString(R.string.keyboardview_keycode_cancel);
+ break;
+ case Keyboard.KEYCODE_DELETE:
+ text = mContext.getString(R.string.keyboardview_keycode_delete);
+ break;
+ case Keyboard.KEYCODE_DONE:
+ text = mContext.getString(R.string.keyboardview_keycode_done);
+ break;
+ case Keyboard.KEYCODE_MODE_CHANGE:
+ text = mContext.getString(R.string.keyboardview_keycode_mode_change);
+ break;
+ case Keyboard.KEYCODE_SHIFT:
+ text = mContext.getString(R.string.keyboardview_keycode_shift);
+ break;
+ case '\n':
+ text = mContext.getString(R.string.keyboardview_keycode_enter);
+ break;
+ default:
+ text = String.valueOf((char) code);
}
event.getText().add(text);
mAccessibilityManager.sendAccessibilityEvent(event);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 719a9577f80e..e6f3021613c4 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1442,8 +1442,8 @@ public class ConnectivityManager {
l.networkCapabilities = netCap;
l.delay = delay;
l.expireSequenceNumber = 0;
- l.networkRequest = sendRequestForNetwork(netCap, l.networkCallback, 0,
- REQUEST, type);
+ l.networkRequest = sendRequestForNetwork(
+ netCap, l.networkCallback, 0, REQUEST, type, getDefaultHandler());
if (l.networkRequest == null) return null;
sLegacyRequests.put(netCap, l);
sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay);
@@ -1453,7 +1453,7 @@ public class ConnectivityManager {
private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) {
if (delay >= 0) {
Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay);
- CallbackHandler handler = getHandler();
+ CallbackHandler handler = getDefaultHandler();
Message msg = handler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap);
handler.sendMessageDelayed(msg, delay);
}
@@ -2780,6 +2780,10 @@ public class ConnectivityManager {
super(looper);
}
+ CallbackHandler(Handler handler) {
+ this(handler.getLooper());
+ }
+
@Override
public void handleMessage(Message message) {
NetworkRequest request = getObject(message, NetworkRequest.class);
@@ -2889,7 +2893,7 @@ public class ConnectivityManager {
}
}
- private CallbackHandler getHandler() {
+ private CallbackHandler getDefaultHandler() {
synchronized (sCallbacks) {
if (sCallbackHandler == null) {
sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper());
@@ -2904,11 +2908,6 @@ public class ConnectivityManager {
private static final int LISTEN = 1;
private static final int REQUEST = 2;
- private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
- NetworkCallback callback, int timeoutMs, int action, int legacyType) {
- return sendRequestForNetwork(need, callback, timeoutMs, action, legacyType, getHandler());
- }
-
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
int timeoutMs, int action, int legacyType, CallbackHandler handler) {
if (callback == null) {
@@ -2954,8 +2953,18 @@ public class ConnectivityManager {
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
int timeoutMs, int legacyType) {
- sendRequestForNetwork(request.networkCapabilities, networkCallback, timeoutMs, REQUEST,
- legacyType);
+ requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
+ }
+
+ /**
+ * Helper function to request a network with a particular legacy type.
+ * @hide
+ */
+ private void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
+ int timeoutMs, int legacyType, Handler handler) {
+ CallbackHandler cbHandler = new CallbackHandler(handler);
+ NetworkCapabilities nc = request.networkCapabilities;
+ sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler);
}
/**
@@ -2981,15 +2990,51 @@ public class ConnectivityManager {
* {@link android.provider.Settings.System#canWrite}.</p>
*
* @param request {@link NetworkRequest} describing this request.
- * @param networkCallback The {@link NetworkCallback} to be utilized for this
- * request. Note the callback must not be shared - they
- * uniquely specify this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
+ * The callback is invoked on the default internal Handler.
* @throws IllegalArgumentException if {@code request} specifies any mutable
* {@code NetworkCapabilities}.
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback) {
- requestNetwork(request, networkCallback, 0,
- inferLegacyTypeForNetworkCapabilities(request.networkCapabilities));
+ requestNetwork(request, networkCallback, getDefaultHandler());
+ }
+
+ /**
+ * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
+ *
+ * This {@link NetworkRequest} will live until released via
+ * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits.
+ * Status of the request can be followed by listening to the various
+ * callbacks described in {@link NetworkCallback}. The {@link Network}
+ * can be used to direct traffic to the network.
+ * <p>It is presently unsupported to request a network with mutable
+ * {@link NetworkCapabilities} such as
+ * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+ * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
+ * as these {@code NetworkCapabilities} represent states that a particular
+ * network may never attain, and whether a network will attain these states
+ * is unknown prior to bringing up the network so the framework does not
+ * know how to go about satisfing a request with these capabilities.
+ *
+ * <p>This method requires the caller to hold either the
+ * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
+ * or the ability to modify system settings as determined by
+ * {@link android.provider.Settings.System#canWrite}.</p>
+ *
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @throws IllegalArgumentException if {@code request} specifies any mutable
+ * {@code NetworkCapabilities}.
+ * @hide
+ */
+ public void requestNetwork(
+ NetworkRequest request, NetworkCallback networkCallback, Handler handler) {
+ int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+ CallbackHandler cbHandler = new CallbackHandler(handler);
+ requestNetwork(request, networkCallback, 0, legacyType, cbHandler);
}
/**
@@ -3007,17 +3052,48 @@ public class ConnectivityManager {
* {@link android.provider.Settings.System#canWrite}.</p>
*
* @param request {@link NetworkRequest} describing this request.
- * @param networkCallback The callbacks to be utilized for this request. Note
- * the callbacks must not be shared - they uniquely specify
- * this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
+ * The callback is invoked on the default internal Handler.
* @param timeoutMs The time in milliseconds to attempt looking for a suitable network
* before {@link NetworkCallback#onUnavailable()} is called.
* @hide
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
int timeoutMs) {
- requestNetwork(request, networkCallback, timeoutMs,
- inferLegacyTypeForNetworkCapabilities(request.networkCapabilities));
+ int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+ requestNetwork(request, networkCallback, timeoutMs, legacyType);
+ }
+
+
+ /**
+ * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
+ * by a timeout.
+ *
+ * This function behaves identically to the non-timedout version, but if a suitable
+ * network is not found within the given time (in milliseconds) the
+ * {@link NetworkCallback#onUnavailable} callback is called. The request must
+ * still be released normally by calling {@link unregisterNetworkCallback(NetworkCallback)}.
+ *
+ * <p>This method requires the caller to hold either the
+ * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
+ * or the ability to modify system settings as determined by
+ * {@link android.provider.Settings.System#canWrite}.</p>
+ *
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
+ * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
+ * before {@link NetworkCallback#onUnavailable} is called.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ *
+ * @hide
+ */
+ public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
+ int timeoutMs, Handler handler) {
+ int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+ CallbackHandler cbHandler = new CallbackHandler(handler);
+ requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler);
}
/**
@@ -3131,9 +3207,30 @@ public class ConnectivityManager {
* @param request {@link NetworkRequest} describing this request.
* @param networkCallback The {@link NetworkCallback} that the system will call as suitable
* networks change state.
+ * The callback is invoked on the default internal Handler.
*/
public void registerNetworkCallback(NetworkRequest request, NetworkCallback networkCallback) {
- sendRequestForNetwork(request.networkCapabilities, networkCallback, 0, LISTEN, TYPE_NONE);
+ registerNetworkCallback(request, networkCallback, getDefaultHandler());
+ }
+
+ /**
+ * Registers to receive notifications about all networks which satisfy the given
+ * {@link NetworkRequest}. The callbacks will continue to be called until
+ * either the application exits or link #unregisterNetworkCallback(NetworkCallback)} is called.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
+ * networks change state.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @hide
+ */
+ public void registerNetworkCallback(
+ NetworkRequest request, NetworkCallback networkCallback, Handler handler) {
+ CallbackHandler cbHandler = new CallbackHandler(handler);
+ NetworkCapabilities nc = request.networkCapabilities;
+ sendRequestForNetwork(nc, networkCallback, 0, LISTEN, TYPE_NONE, cbHandler);
}
/**
@@ -3185,8 +3282,25 @@ public class ConnectivityManager {
*
* @param networkCallback The {@link NetworkCallback} that the system will call as the
* system default network changes.
+ * The callback is invoked on the default internal Handler.
*/
public void registerDefaultNetworkCallback(NetworkCallback networkCallback) {
+ registerDefaultNetworkCallback(networkCallback, getDefaultHandler());
+ }
+
+ /**
+ * Registers to receive notifications about changes in the system default network. The callbacks
+ * will continue to be called until either the application exits or
+ * {@link #unregisterNetworkCallback(NetworkCallback)} is called.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * @param networkCallback The {@link NetworkCallback} that the system will call as the
+ * system default network changes.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @hide
+ */
+ public void registerDefaultNetworkCallback(NetworkCallback networkCallback, Handler handler) {
// This works because if the NetworkCapabilities are null,
// ConnectivityService takes them from the default request.
//
@@ -3194,7 +3308,8 @@ public class ConnectivityManager {
// capabilities, this request is guaranteed, at all times, to be
// satisfied by the same network, if any, that satisfies the default
// request, i.e., the system default network.
- sendRequestForNetwork(null, networkCallback, 0, REQUEST, TYPE_NONE);
+ CallbackHandler cbHandler = new CallbackHandler(handler);
+ sendRequestForNetwork(null, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler);
}
/**
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 7c015deae8f5..280fa2ca9496 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -432,14 +432,13 @@ public class FileUtils {
*/
public static boolean contains(File dir, File file) {
if (dir == null || file == null) return false;
+ return contains(dir.getAbsolutePath(), file.getAbsolutePath());
+ }
- String dirPath = dir.getAbsolutePath();
- String filePath = file.getAbsolutePath();
-
+ public static boolean contains(String dirPath, String filePath) {
if (dirPath.equals(filePath)) {
return true;
}
-
if (!dirPath.endsWith("/")) {
dirPath += "/";
}
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 7702c174ba2f..8882672c5210 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -546,6 +546,25 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
}
/**
+ * Return the filesystem path of the real file on disk that is represented
+ * by the given {@link FileDescriptor}.
+ *
+ * @hide
+ */
+ public static File getFile(FileDescriptor fd) throws IOException {
+ try {
+ final String path = Os.readlink("/proc/self/fd/" + fd.getInt$());
+ if (OsConstants.S_ISREG(Os.stat(path).st_mode)) {
+ return new File(path);
+ } else {
+ throw new IOException("Not a regular file: " + path);
+ }
+ } catch (ErrnoException e) {
+ throw e.rethrowAsIOException();
+ }
+ }
+
+ /**
* Retrieve the actual FileDescriptor associated with this object.
*
* @return Returns the FileDescriptor associated with this object.
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 9e35bf68d78c..2cc4b7170f38 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -293,6 +293,6 @@ interface IStorageManager {
ParcelFileDescriptor openProxyFileDescriptor(int mountPointId, int fileId, int mode) = 74;
long getCacheQuotaBytes(String volumeUuid, int uid) = 75;
long getCacheSizeBytes(String volumeUuid, int uid) = 76;
- long getAllocatableBytes(String path, int flags) = 77;
- void allocateBytes(String path, long bytes, int flags) = 78;
+ long getAllocatableBytes(String volumeUuid, int flags) = 77;
+ void allocateBytes(String volumeUuid, long bytes, int flags) = 78;
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2a3c03d1f84f..e070c6e8423f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -16,6 +16,7 @@
package android.os.storage;
+import static android.net.TrafficStats.GB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import android.annotation.IntDef;
@@ -675,6 +676,36 @@ public class StorageManager {
}
/** {@hide} */
+ public @Nullable String findUuidForPath(File path) {
+ Preconditions.checkNotNull(path);
+ final String pathString = path.getAbsolutePath();
+ if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) {
+ return StorageManager.UUID_PRIVATE_INTERNAL;
+ }
+ try {
+ for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
+ if (vol.path != null && FileUtils.contains(vol.path, pathString)) {
+ // TODO: verify that emulated adopted devices have UUID of
+ // underlying volume
+ return vol.fsUuid;
+ }
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ throw new IllegalStateException("Failed to find a storage device for " + path);
+ }
+
+ /** {@hide} */
+ public @Nullable File findPathForUuid(String volumeUuid) {
+ final VolumeInfo vol = findVolumeByQualifiedUuid(volumeUuid);
+ if (vol != null) {
+ return vol.getPath();
+ }
+ throw new IllegalStateException("Failed to find a storage device for " + volumeUuid);
+ }
+
+ /** {@hide} */
public @NonNull List<VolumeInfo> getVolumes() {
try {
return Arrays.asList(mStorageManager.getVolumes(0));
@@ -1069,9 +1100,12 @@ public class StorageManager {
throw new IllegalStateException("Missing primary storage");
}
- /** {@hide} */
- private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
+ private static final int DEFAULT_THRESHOLD_PERCENTAGE = 5;
private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
+
+ private static final int DEFAULT_CACHE_PERCENTAGE = 10;
+ private static final long DEFAULT_CACHE_MAX_BYTES = 5 * GB_IN_BYTES;
+
private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
/**
@@ -1102,6 +1136,23 @@ public class StorageManager {
}
/**
+ * Return the minimum number of bytes of storage on the device that should
+ * be reserved for cached data.
+ *
+ * @hide
+ */
+ public long getStorageCacheBytes(File path) {
+ final long cachePercent = Settings.Global.getInt(mResolver,
+ Settings.Global.SYS_STORAGE_CACHE_PERCENTAGE, DEFAULT_CACHE_PERCENTAGE);
+ final long cacheBytes = (path.getTotalSpace() * cachePercent) / 100;
+
+ final long maxCacheBytes = Settings.Global.getLong(mResolver,
+ Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES, DEFAULT_CACHE_MAX_BYTES);
+
+ return Math.min(cacheBytes, maxCacheBytes);
+ }
+
+ /**
* Return the number of available bytes at which the given path is
* considered full.
*
@@ -1409,40 +1460,37 @@ public class StorageManager {
}
/**
- * Return quota size in bytes for cached data belonging to the calling app.
+ * Return quota size in bytes for all cached data belonging to the calling
+ * app on the filesystem that hosts the given path.
* <p>
* If your app goes above this quota, your cached files will be some of the
* first to be deleted when additional disk space is needed. Conversely, if
* your app stays under this quota, your cached files will be some of the
* last to be deleted when additional disk space is needed.
* <p>
- * This quota may change over time depending on how frequently the user
+ * This quota will change over time depending on how frequently the user
* interacts with your app, and depending on how much disk space is used.
- * <p>
- * Cached data tracked by this method always includes
- * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
- * it also includes {@link Context#getExternalCacheDir()} if the primary
- * shared/external storage is hosted on the same storage device as your
- * private data.
* <p class="note">
* Note: if your app uses the {@code android:sharedUserId} manifest feature,
* then cached data for all packages in your shared UID is tracked together
* as a single unit.
* </p>
*
- * @see #getCacheSizeBytes()
+ * @see #getCacheSizeBytes(File)
*/
- public long getCacheQuotaBytes() {
+ public long getCacheQuotaBytes(File path) {
try {
+ final String volumeUuid = findUuidForPath(path);
final ApplicationInfo app = mContext.getApplicationInfo();
- return mStorageManager.getCacheQuotaBytes(app.volumeUuid, app.uid);
+ return mStorageManager.getCacheQuotaBytes(volumeUuid, app.uid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Return total size in bytes of cached data belonging to the calling app.
+ * Return total size in bytes of all cached data belonging to the calling
+ * app on the filesystem that hosts the given path.
* <p>
* Cached data tracked by this method always includes
* {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
@@ -1457,67 +1505,38 @@ public class StorageManager {
*
* @see #getCacheQuotaBytes()
*/
- public long getCacheSizeBytes() {
+ public long getCacheSizeBytes(File path) {
try {
+ final String volumeUuid = findUuidForPath(path);
final ApplicationInfo app = mContext.getApplicationInfo();
- return mStorageManager.getCacheSizeBytes(app.volumeUuid, app.uid);
+ return mStorageManager.getCacheSizeBytes(volumeUuid, app.uid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- /**
- * Return quota size in bytes for cached data on primary shared/external
- * storage belonging to the calling app.
- * <p>
- * If primary shared/external storage is hosted on the same storage device
- * as your private data, this method will return -1, since all data stored
- * under {@link Context#getExternalCacheDir()} will be counted under
- * {@link #getCacheQuotaBytes()}.
- * <p class="note">
- * Note: if your app uses the {@code android:sharedUserId} manifest feature,
- * then cached data for all packages in your shared UID is tracked together
- * as a single unit.
- * </p>
- */
+ /** @removed */
+ @Deprecated
+ public long getCacheQuotaBytes() {
+ return getCacheQuotaBytes(mContext.getCacheDir());
+ }
+
+ /** @removed */
+ @Deprecated
+ public long getCacheSizeBytes() {
+ return getCacheSizeBytes(mContext.getCacheDir());
+ }
+
+ /** @removed */
+ @Deprecated
public long getExternalCacheQuotaBytes() {
- final ApplicationInfo app = mContext.getApplicationInfo();
- final String primaryUuid = getPrimaryStorageUuid();
- if (Objects.equals(app.volumeUuid, primaryUuid)) {
- return -1;
- }
- try {
- return mStorageManager.getCacheQuotaBytes(primaryUuid, app.uid);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCacheQuotaBytes(mContext.getExternalCacheDir());
}
- /**
- * Return total size in bytes of cached data on primary shared/external
- * storage belonging to the calling app.
- * <p>
- * If primary shared/external storage is hosted on the same storage device
- * as your private data, this method will return -1, since all data stored
- * under {@link Context#getExternalCacheDir()} will be counted under
- * {@link #getCacheQuotaBytes()}.
- * <p class="note">
- * Note: if your app uses the {@code android:sharedUserId} manifest feature,
- * then cached data for all packages in your shared UID is tracked together
- * as a single unit.
- * </p>
- */
+ /** @removed */
+ @Deprecated
public long getExternalCacheSizeBytes() {
- final ApplicationInfo app = mContext.getApplicationInfo();
- final String primaryUuid = getPrimaryStorageUuid();
- if (Objects.equals(app.volumeUuid, primaryUuid)) {
- return -1;
- }
- try {
- return mStorageManager.getCacheSizeBytes(primaryUuid, app.uid);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCacheSizeBytes(mContext.getExternalCacheDir());
}
/**
@@ -1551,28 +1570,30 @@ public class StorageManager {
* Return the maximum number of new bytes that your app can allocate for
* itself using {@link #allocateBytes(File, long, int)} at the given path.
* This value is typically larger than {@link File#getUsableSpace()}, since
- * the system may automatically delete cached files to satisfy your request.
+ * the system may be willing to delete cached files to satisfy an allocation
+ * request.
* <p>
* This method is best used as a pre-flight check, such as deciding if there
* is enough space to store an entire music album before you allocate space
* for each audio file in the album. Attempts to allocate disk space beyond
- * this value will fail.
+ * the returned value will fail.
* <p class="note">
* Note: if your app uses the {@code android:sharedUserId} manifest feature,
* then allocatable space for all packages in your shared UID is tracked
* together as a single unit.
* </p>
*
- * @param file the directory where you're considering allocating disk space,
+ * @param path the path where you're considering allocating disk space,
* since allocatable space can vary widely depending on the
* underlying storage device.
* @param flags to apply to the request.
* @return the maximum number of new bytes that the calling app can allocate
* using {@link #allocateBytes(File, long, int)}.
*/
- public long getAllocatableBytes(File file, @AllocateFlags int flags) throws IOException {
+ public long getAllocatableBytes(File path, @AllocateFlags int flags) throws IOException {
try {
- return mStorageManager.getAllocatableBytes(file.getAbsolutePath(), flags);
+ final String volumeUuid = findUuidForPath(path);
+ return mStorageManager.getAllocatableBytes(volumeUuid, flags);
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -1594,14 +1615,15 @@ public class StorageManager {
* {@link #allocateBytes(FileDescriptor, long, int)} which will guarantee
* that bytes are allocated to an opened file.
*
- * @param file the directory where you'd like to allocate disk space.
+ * @param path the path where you'd like to allocate disk space.
* @param bytes the number of bytes to allocate.
* @param flags to apply to the request.
* @see #getAllocatableBytes(File, int)
*/
- public void allocateBytes(File file, long bytes, @AllocateFlags int flags) throws IOException {
+ public void allocateBytes(File path, long bytes, @AllocateFlags int flags) throws IOException {
try {
- mStorageManager.allocateBytes(file.getAbsolutePath(), bytes, flags);
+ final String volumeUuid = findUuidForPath(path);
+ mStorageManager.allocateBytes(volumeUuid, bytes, flags);
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
} catch (RemoteException e) {
@@ -1610,37 +1632,39 @@ public class StorageManager {
}
/**
- * Allocate the requested number of bytes for your application to use at the
- * given path. This will cause the system to delete any cached files
+ * Allocate the requested number of bytes for your application to use in the
+ * given open file. This will cause the system to delete any cached files
* necessary to satisfy your request.
* <p>
* Attempts to allocate disk space beyond the value returned by
* {@link #getAllocatableBytes(File, int)} will fail.
* <p>
- * This method guarantees that bytes are allocated to the opened file,
- * otherwise it will throw if fast allocation not possible. Fast allocation
- * is typically only supported in private app data directories, and on
- * shared/external storage devices which are emulated.
+ * This method guarantees that bytes have been allocated to the opened file,
+ * otherwise it will throw if fast allocation is not possible. Fast
+ * allocation is typically only supported in private app data directories,
+ * and on shared/external storage devices which are emulated.
*
- * @param fd the directory where you'd like to allocate disk space.
- * @param bytes the number of bytes to allocate.
+ * @param fd the open file that you'd like to allocate disk space for.
+ * @param bytes the number of bytes to allocate. This is the desired final
+ * size of the open file.
* @param flags to apply to the request.
* @see #getAllocatableBytes(File, int)
* @see Environment#isExternalStorageEmulated(File)
*/
public void allocateBytes(FileDescriptor fd, long bytes, @AllocateFlags int flags)
throws IOException {
- final File file;
- try {
- file = new File(Os.readlink("/proc/self/fd/" + fd.getInt$()));
- } catch (ErrnoException e) {
- throw e.rethrowAsIOException();
- }
+ final File file = ParcelFileDescriptor.getFile(fd);
for (int i = 0; i < 3; i++) {
- allocateBytes(file, bytes, flags);
-
try {
+ final long haveBytes = Os.fstat(fd).st_blocks * 512;
+ final long needBytes = bytes - haveBytes;
+
+ if (needBytes > 0) {
+ allocateBytes(file, needBytes, flags);
+ }
+
Os.posix_fallocate(fd, 0, bytes);
+ return;
} catch (ErrnoException e) {
if (e.errno == OsConstants.ENOSPC) {
Log.w(TAG, "Odd, not enough space; let's try again?");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c9b1c9cf2703..6c319abb641b 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5217,6 +5217,18 @@ public final class Settings {
public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
/**
+ * A flag to tell {@link com.android.server.devicepolicy.DevicePolicyManagerService} that
+ * the default for {@link #INSTALL_NON_MARKET_APPS} is reversed for this user on OTA. So it
+ * can set the restriction {@link android.os.UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}
+ * on behalf of the profile owner if needed to make the change transparent for profile
+ * owners.
+ *
+ * @hide
+ */
+ public static final String UNKNOWN_SOURCES_DEFAULT_REVERSED =
+ "unknown_sources_default_reversed";
+
+ /**
* Comma-separated list of location providers that activities may access. Do not rely on
* this value being present in settings.db or on ContentObserver notifications on the
* corresponding Uri.
@@ -5492,7 +5504,12 @@ public final class Settings {
/**
* Whether to speak passwords while in accessibility mode.
+ *
+ * @deprecated The speaking of passwords is controlled by individual accessibility services.
+ * Apps should ignore this setting and provide complete information to accessibility
+ * at all times, which was the behavior when this value was {@code true}.
*/
+ @Deprecated
public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
/**
@@ -8578,6 +8595,24 @@ public final class Settings {
SYS_STORAGE_FULL_THRESHOLD_BYTES = "sys_storage_full_threshold_bytes";
/**
+ * Minimum percentage of storage on the device that is reserved for
+ * cached data.
+ *
+ * @hide
+ */
+ public static final String
+ SYS_STORAGE_CACHE_PERCENTAGE = "sys_storage_cache_percentage";
+
+ /**
+ * Maximum bytes of storage on the device that is reserved for cached
+ * data.
+ *
+ * @hide
+ */
+ public static final String
+ SYS_STORAGE_CACHE_MAX_BYTES = "sys_storage_cache_max_bytes";
+
+ /**
* The maximum reconnect delay for short network outages or when the
* network is suspended due to phone use.
*
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 59b494c3f8a6..d76d444e7d33 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -106,15 +106,13 @@ public final class Dataset implements Parcelable {
private boolean mDestroyed;
/**
- * Sets the presentation used to visualize this dataset.
+ * Creates a new builder.
*
- * @param presentation The presentation view.
- *
- * @return This builder.
+ * @param presentation The presentation used to visualize this dataset.
*/
- public @NonNull Builder setPresentation(@Nullable RemoteViews presentation) {
+ public Builder(@NonNull RemoteViews presentation) {
+ Preconditions.checkNotNull(presentation, "presentation must be non-null");
mPresentation = presentation;
- return this;
}
/**
@@ -201,9 +199,6 @@ public final class Dataset implements Parcelable {
throw new IllegalArgumentException(
"at least one value must be set");
}
- if (mPresentation == null) {
- throw new IllegalArgumentException("presentation must be set");
- }
return new Dataset(this);
}
@@ -225,9 +220,9 @@ public final class Dataset implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeParcelable(mPresentation, flags);
parcel.writeTypedArrayList(mFieldIds, flags);
parcel.writeTypedArrayList(mFieldValues, flags);
- parcel.writeParcelable(mPresentation, flags);
parcel.writeParcelable(mAuthentication, flags);
}
@@ -237,7 +232,7 @@ public final class Dataset implements Parcelable {
// Always go through the builder to ensure the data ingested by
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
- final Builder builder = new Builder();
+ final Builder builder = new Builder(parcel.readParcelable(null));
final ArrayList<AutoFillId> ids = parcel.readTypedArrayList(null);
final ArrayList<AutoFillValue> values = parcel.readTypedArrayList(null);
final int idCount = (ids != null) ? ids.size() : 0;
@@ -247,7 +242,6 @@ public final class Dataset implements Parcelable {
AutoFillValue value = (valueCount > i) ? values.get(i) : null;
builder.setValue(id, value);
}
- builder.setPresentation(parcel.readParcelable(null));
builder.setAuthentication(parcel.readParcelable(null));
return builder.build();
}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index bac43915281a..91c668ef32e2 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -28,6 +28,8 @@ import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillManager;
import android.widget.RemoteViews;
+import java.util.ArrayList;
+
/**
* Response for a {@link
* AutoFillService#onFillRequest(android.app.assist.AssistStructure,
@@ -43,8 +45,7 @@ import android.widget.RemoteViews;
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .add(new Dataset.Builder()
- * .setPresentation(createPresentation())
+ * .add(new Dataset.Builder(createPresentation())
* .setTextFieldValue(id1, "homer")
* .setTextFieldValue(id2, "D'OH!")
* .build())
@@ -55,13 +56,11 @@ import android.widget.RemoteViews;
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .add(new Dataset.Builder()
- * .setPresentation(createFirstPresentation())
+ * .add(new Dataset.Builder(createFirstPresentation())
* .setTextFieldValue(id1, "homer")
* .setTextFieldValue(id2, "D'OH!")
* .build())
- * .add(new Dataset.Builder()
- * .setPresentation(createSecondPresentation())
+ * .add(new Dataset.Builder(createSecondPresentation())
* .setTextFieldValue(id1, "elbarto")
* .setTextFieldValue(id2, "cowabonga")
* .build())
@@ -85,8 +84,7 @@ import android.widget.RemoteViews;
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .add(new Dataset.Builder(")
- * .setPresentation(createPresentation())
+ * .add(new Dataset.Builder(createPresentation())
* .setTextFieldValue(id1, "Homer") // first name
* .setTextFieldValue(id2, "Simpson") // last name
* .setTextFieldValue(id3, "742 Evergreen Terrace") // street
@@ -114,13 +112,11 @@ import android.widget.RemoteViews;
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .add(new Dataset.Builder()
- * .setPresentation(createFirstPresentation())
+ * .add(new Dataset.Builder(createFirstPresentation())
* .setTextFieldValue(id1, "Homer")
* .setTextFieldValue(id2, "Simpson")
* .build())
- * .add(new Dataset.Builder()
- * .setPresentation(createSecondPresentation())
+ * .add(new Dataset.Builder(createSecondPresentation())
* .setTextFieldValue(id1, "Bart")
* .setTextFieldValue(id2, "Simpson")
* .build())
@@ -132,13 +128,11 @@ import android.widget.RemoteViews;
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .add(new Dataset.Builder()
- * .setPresentation(createThirdPresentation())
+ * .add(new Dataset.Builder(createThirdPresentation())
* .setTextFieldValue(id3, "742 Evergreen Terrace")
* .setTextFieldValue(id4, "Springfield")
* .build())
- * .add(new Dataset.Builder()
- * .setPresentation(createFourthPresentation())
+ * .add(new Dataset.Builder(createFourthPresentation())
* .setTextFieldValue(id3, "Springfield Power Plant")
* .setTextFieldValue(id4, "Springfield")
* .build())
@@ -163,7 +157,7 @@ import android.widget.RemoteViews;
*/
public final class FillResponse implements Parcelable {
- private final ArraySet<Dataset> mDatasets;
+ private final ArrayList<Dataset> mDatasets;
private final ArraySet<AutoFillId> mSavableIds;
private final Bundle mExtras;
private final RemoteViews mPresentation;
@@ -183,7 +177,7 @@ public final class FillResponse implements Parcelable {
}
/** @hide */
- public @Nullable ArraySet<Dataset> getDatasets() {
+ public @Nullable ArrayList<Dataset> getDatasets() {
return mDatasets;
}
@@ -207,7 +201,7 @@ public final class FillResponse implements Parcelable {
* one dataset or set an authentication intent with a presentation view.
*/
public static final class Builder {
- private ArraySet<Dataset> mDatasets;
+ private ArrayList<Dataset> mDatasets;
private ArraySet<AutoFillId> mSavableIds;
private Bundle mExtras;
private RemoteViews mPresentation;
@@ -215,23 +209,6 @@ public final class FillResponse implements Parcelable {
private boolean mDestroyed;
/**
- * Sets the presentation used to visualize this response. You should
- * set this only if you need an authentication as this is the only
- * case the response needs to be presented to the user.
- *
- * @param presentation The presentation view.
- *
- * @return This builder.
- *
- * @see #setAuthentication(IntentSender)
- */
- public @NonNull
- FillResponse.Builder setPresentation(@Nullable RemoteViews presentation) {
- mPresentation = presentation;
- return this;
- }
-
- /**
* Requires a fill response authentication before auto-filling the activity with
* any data set in this response.
*
@@ -257,19 +234,29 @@ public final class FillResponse implements Parcelable {
* available data sets some of which may need to be further authenticated, for
* example a credit card whose CVV needs to be entered.</p>
*
+ * <p>If you provide an authentication intent you must also provide a presentation
+ * which is used to visualize visualize the response for triggering the authentication
+ * flow.</p>
+ *
* <p></><strong>Note:</strong> Do not make the provided pending intent
* immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
* platform needs to fill in the authentication arguments.</p>
*
* @param authentication Intent to an activity with your authentication flow.
+ * @param presentation The presentation to visualize the response.
* @return This builder.
*
* @see android.app.PendingIntent#getIntentSender()
- * @see #setPresentation(RemoteViews)
*/
- public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) {
+ public @NonNull Builder setAuthentication(@Nullable IntentSender authentication,
+ @Nullable RemoteViews presentation) {
throwIfDestroyed();
+ if (authentication == null ^ presentation == null) {
+ throw new IllegalArgumentException("authentication and presentation"
+ + " must be both non-null or null");
+ }
mAuthentication = authentication;
+ mPresentation = presentation;
return this;
}
@@ -284,7 +271,7 @@ public final class FillResponse implements Parcelable {
return this;
}
if (mDatasets == null) {
- mDatasets = new ArraySet<>();
+ mDatasets = new ArrayList<>();
}
if (!mDatasets.add(dataset)) {
return this;
@@ -353,10 +340,6 @@ public final class FillResponse implements Parcelable {
*/
public FillResponse build() {
throwIfDestroyed();
- if (mAuthentication == null ^ mPresentation == null) {
- throw new IllegalArgumentException("authentication and presentation"
- + " must be both non-null or null");
- }
if (mAuthentication == null && mDatasets == null && mSavableIds == null) {
throw new IllegalArgumentException("need to provide at least one"
+ " data set or savable ids or an authentication with a presentation");
@@ -398,11 +381,11 @@ public final class FillResponse implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeTypedArraySet(mDatasets, flags);
+ parcel.writeTypedArrayList(mDatasets, flags);
parcel.writeTypedArraySet(mSavableIds, flags);
parcel.writeParcelable(mExtras, flags);
- parcel.writeParcelable(mPresentation, flags);
parcel.writeParcelable(mAuthentication, flags);
+ parcel.writeParcelable(mPresentation, flags);
}
public static final Parcelable.Creator<FillResponse> CREATOR =
@@ -413,10 +396,10 @@ public final class FillResponse implements Parcelable {
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
final Builder builder = new Builder();
- final ArraySet<Dataset> datasets = parcel.readTypedArraySet(null);
+ final ArrayList<Dataset> datasets = parcel.readTypedArrayList(null);
final int datasetCount = (datasets != null) ? datasets.size() : 0;
for (int i = 0; i < datasetCount; i++) {
- builder.addDataset(datasets.valueAt(i));
+ builder.addDataset(datasets.get(i));
}
final ArraySet<AutoFillId> fillIds = parcel.readTypedArraySet(null);
final int fillIdCount = (fillIds != null) ? fillIds.size() : 0;
@@ -424,8 +407,8 @@ public final class FillResponse implements Parcelable {
builder.addSavableFields(fillIds.valueAt(i));
}
builder.setExtras(parcel.readParcelable(null));
- builder.setPresentation(parcel.readParcelable(null));
- builder.setAuthentication(parcel.readParcelable(null));
+ builder.setAuthentication(parcel.readParcelable(null),
+ parcel.readParcelable(null));
return builder.build();
}
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 60d8a0fc8894..4b02df86c82e 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -53,16 +53,12 @@ import java.lang.reflect.Array;
* @param end End index in the source object.
*/
private final void copySpans(Spanned src, int start, int end) {
- final Object[] spans = src.getSpans(start, end, Object.class);
+ Object[] spans = src.getSpans(start, end, Object.class);
for (int i = 0; i < spans.length; i++) {
- if (spans[i] instanceof NoCopySpan) {
- continue;
- }
-
int st = src.getSpanStart(spans[i]);
int en = src.getSpanEnd(spans[i]);
- final int fl = src.getSpanFlags(spans[i]);
+ int fl = src.getSpanFlags(spans[i]);
if (st < start)
st = start;
@@ -82,42 +78,33 @@ import java.lang.reflect.Array;
* @param end End index in the source object.
*/
private final void copySpans(SpannableStringInternal src, int start, int end) {
- int count = 0;
- boolean includesNoCopySpan = false;
- final int[] srcData = src.mSpanData;
- final Object[] srcSpans = src.mSpans;
- final int limit = src.mSpanCount;
-
- for (int i = 0; i < limit; i++) {
- int spanStart = srcData[i * COLUMNS + START];
- int spanEnd = srcData[i * COLUMNS + END];
- if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
- if (srcSpans[i] instanceof NoCopySpan) {
- includesNoCopySpan = true;
- continue;
- }
- count++;
- }
-
- if (count == 0) return;
-
- if (!includesNoCopySpan && start == 0 && end == src.length()) {
+ if (start == 0 && end == src.length()) {
mSpans = ArrayUtils.newUnpaddedObjectArray(src.mSpans.length);
mSpanData = new int[src.mSpanData.length];
mSpanCount = src.mSpanCount;
System.arraycopy(src.mSpans, 0, mSpans, 0, src.mSpans.length);
System.arraycopy(src.mSpanData, 0, mSpanData, 0, mSpanData.length);
} else {
+ int count = 0;
+ int[] srcData = src.mSpanData;
+ int limit = src.mSpanCount;
+ for (int i = 0; i < limit; i++) {
+ int spanStart = srcData[i * COLUMNS + START];
+ int spanEnd = srcData[i * COLUMNS + END];
+ if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
+ count++;
+ }
+
+ if (count == 0) return;
+
+ Object[] srcSpans = src.mSpans;
mSpanCount = count;
mSpans = ArrayUtils.newUnpaddedObjectArray(mSpanCount);
mSpanData = new int[mSpans.length * COLUMNS];
for (int i = 0, j = 0; i < limit; i++) {
int spanStart = srcData[i * COLUMNS + START];
int spanEnd = srcData[i * COLUMNS + END];
- if (isOutOfCopyRange(start, end, spanStart, spanEnd)
- || srcSpans[i] instanceof NoCopySpan) {
- continue;
- }
+ if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
if (spanStart < start) spanStart = start;
if (spanEnd > end) spanEnd = end;
diff --git a/core/java/android/view/IGraphicsStats.aidl b/core/java/android/view/IGraphicsStats.aidl
index c235eb261ee6..e6b750b73406 100644
--- a/core/java/android/view/IGraphicsStats.aidl
+++ b/core/java/android/view/IGraphicsStats.aidl
@@ -17,10 +17,11 @@
package android.view;
import android.os.ParcelFileDescriptor;
+import android.view.IGraphicsStatsCallback;
/**
* @hide
*/
interface IGraphicsStats {
- ParcelFileDescriptor requestBufferForProcess(String packageName, IBinder token);
+ ParcelFileDescriptor requestBufferForProcess(String packageName, IGraphicsStatsCallback callback);
}
diff --git a/core/java/android/view/IGraphicsStatsCallback.aidl b/core/java/android/view/IGraphicsStatsCallback.aidl
new file mode 100644
index 000000000000..f70e1419c317
--- /dev/null
+++ b/core/java/android/view/IGraphicsStatsCallback.aidl
@@ -0,0 +1,24 @@
+/**
+ * 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 android.view;
+
+/**
+ * @hide
+ */
+oneway interface IGraphicsStatsCallback {
+ void onRotateGraphicsStatsBuffer();
+}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 4ceb23628fb4..c66bf87476a7 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -25,9 +25,9 @@ import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedVectorDrawable;
-import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.util.Log;
@@ -164,6 +164,18 @@ public final class ThreadedRenderer {
public static final String OVERDRAW_PROPERTY_SHOW = "show";
/**
+ * Defines the rendering pipeline to be used by the ThreadedRenderer.
+ *
+ * Possible values:
+ * "opengl", will use the existing OpenGL renderer
+ * "skiagl", will use Skia's OpenGL renderer
+ * "skiavk", will use Skia's Vulkan renderer
+ *
+ * @hide
+ */
+ public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer";
+
+ /**
* Turn on to debug non-rectangular clip operations.
*
* Possible values:
@@ -248,10 +260,10 @@ public final class ThreadedRenderer {
*
* @return A threaded renderer backed by OpenGL.
*/
- public static ThreadedRenderer create(Context context, boolean translucent) {
+ public static ThreadedRenderer create(Context context, boolean translucent, String name) {
ThreadedRenderer renderer = null;
if (isAvailable()) {
- renderer = new ThreadedRenderer(context, translucent);
+ renderer = new ThreadedRenderer(context, translucent, name);
}
return renderer;
}
@@ -275,10 +287,6 @@ public final class ThreadedRenderer {
nOverrideProperty(name, value);
}
- public static void dumpProfileData(byte[] data, FileDescriptor fd) {
- nDumpProfileData(data, fd);
- }
-
// Keep in sync with DrawFrameTask.h SYNC_* flags
// Nothing interesting to report
private static final int SYNC_OK = 0;
@@ -334,7 +342,7 @@ public final class ThreadedRenderer {
private boolean mEnabled;
private boolean mRequested = true;
- ThreadedRenderer(Context context, boolean translucent) {
+ ThreadedRenderer(Context context, boolean translucent, String name) {
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
@@ -348,6 +356,7 @@ public final class ThreadedRenderer {
mRootNode = RenderNode.adopt(rootNodePtr);
mRootNode.setClipToBounds(false);
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
+ nSetName(mNativeProxy, name);
ProcessInitializer.sInstance.init(context, mNativeProxy);
@@ -815,15 +824,6 @@ public final class ThreadedRenderer {
}
/**
- * Optional, sets the name of the renderer. Useful for debugging purposes.
- *
- * @param name The name of this renderer, can be null
- */
- void setName(String name) {
- nSetName(mNativeProxy, name);
- }
-
- /**
* Blocks until all previously queued work has completed.
*/
void fence() {
@@ -884,20 +884,29 @@ public final class ThreadedRenderer {
private static class ProcessInitializer {
static ProcessInitializer sInstance = new ProcessInitializer();
- private static IBinder sProcToken;
private boolean mInitialized = false;
+ private Context mAppContext;
+ private IGraphicsStats mGraphicsStatsService;
+ private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+ @Override
+ public void onRotateGraphicsStatsBuffer() throws RemoteException {
+ rotateBuffer();
+ }
+ };
+
private ProcessInitializer() {}
synchronized void init(Context context, long renderProxy) {
if (mInitialized) return;
mInitialized = true;
+ mAppContext = context.getApplicationContext();
initSched(context, renderProxy);
- initGraphicsStats(context, renderProxy);
+ initGraphicsStats();
}
- private static void initSched(Context context, long renderProxy) {
+ private void initSched(Context context, long renderProxy) {
try {
int tid = nGetRenderThreadTid(renderProxy);
ActivityManager.getService().setRenderThread(tid);
@@ -906,17 +915,28 @@ public final class ThreadedRenderer {
}
}
- private static void initGraphicsStats(Context context, long renderProxy) {
+ private void initGraphicsStats() {
try {
IBinder binder = ServiceManager.getService("graphicsstats");
if (binder == null) return;
- IGraphicsStats graphicsStatsService = IGraphicsStats.Stub
- .asInterface(binder);
- sProcToken = new Binder();
- final String pkg = context.getApplicationInfo().packageName;
- ParcelFileDescriptor pfd = graphicsStatsService.
- requestBufferForProcess(pkg, sProcToken);
- nSetProcessStatsBuffer(renderProxy, pfd.getFd());
+ mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+ requestBuffer();
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+ }
+ }
+
+ private void rotateBuffer() {
+ nRotateProcessStatsBuffer();
+ requestBuffer();
+ }
+
+ private void requestBuffer() {
+ try {
+ final String pkg = mAppContext.getApplicationInfo().packageName;
+ ParcelFileDescriptor pfd = mGraphicsStatsService
+ .requestBufferForProcess(pkg, mGraphicsStatsCallback);
+ nSetProcessStatsBuffer(pfd.getFd());
pfd.close();
} catch (Throwable t) {
Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
@@ -936,7 +956,8 @@ public final class ThreadedRenderer {
static native void setupShadersDiskCache(String cacheFile);
- private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
+ private static native void nRotateProcessStatsBuffer();
+ private static native void nSetProcessStatsBuffer(int fd);
private static native int nGetRenderThreadTid(long nativeProxy);
private static native long nCreateRootRenderNode();
@@ -981,7 +1002,6 @@ public final class ThreadedRenderer {
private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
@DumpFlags int dumpFlags);
- private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
boolean placeFront);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index df0a161327f0..aa85a985155b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6983,19 +6983,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Called when assist structure is being retrieved from a view as part of an auto-fill request.
*
- * <p>When implementing this method, subclasses must also:
- *
- * <ol>
- * <li>Implement {@link #autoFill(AutoFillValue)}, {@link #getAutoFillType()}
- * and {@link #getAutoFillValue()}.
- * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
- * AutoFillValue)} when its value changed.
- * </ol>
+ * <p>This method already provides most of what's needed for auto-fill, but should be overridden
+ * when the view contents does not include PII (Personally Identifiable Information) (so it
+ * can call {@link ViewStructure#setSanitized(boolean) ViewStructure#setSanitized(true)}).
*
* @param structure Fill in with structured view data. The default implementation
* fills in all data that can be inferred from the view itself.
* @param flags optional flags (currently {@code 0}).
*/
+ @CallSuper
public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
onProvideStructureForAssistOrAutoFill(structure, true);
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5d01b4162c6f..f16fcc933b70 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -35,7 +35,7 @@ public class ViewConfiguration {
* Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
* dips
*/
- private static final int SCROLL_BAR_SIZE = 10;
+ private static final int SCROLL_BAR_SIZE = 4;
/**
* Duration of the fade when scrollbars fade away in milliseconds
@@ -346,7 +346,8 @@ public class ViewConfiguration {
mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);
mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);
- mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
+ mScrollbarSize = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.config_scrollbarSize);
mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6cdd483370b6..c81e9385897f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -887,9 +887,9 @@ public final class ViewRootImpl implements ViewParent,
final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
|| insets.top != 0 || insets.bottom != 0;
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
- mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent);
+ mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
+ attrs.getTitle().toString());
if (mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.setName(attrs.getTitle().toString());
mAttachInfo.mHardwareAccelerated =
mAttachInfo.mHardwareAccelerationRequested = true;
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 9ce23e631451..bc2725f56bf6 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -31,16 +31,6 @@ import android.view.autofill.AutoFillValue;
public abstract class ViewStructure {
/**
- * Flag used when adding virtual views for auto-fill, it indicates the contents of the view
- * (such as * {@link android.app.assist.AssistStructure.ViewNode#getText()} and
- * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillValue()})
- * can be passed to the {@link
- * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} call.
- */
- public static final int AUTO_FILL_FLAG_SANITIZED = 0x1;
-
- /**
* Set the identifier for this view.
*
* @param id The view's identifier, as per {@link View#getId View.getId()}.
@@ -278,7 +268,7 @@ public abstract class ViewStructure {
*
* @param index child index
* @param virtualId id identifying the virtual child inside the custom view.
- * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
+ * @param flags currently {@code 0}.
*/
// TODO(b/33197203, b/33802548): add CTS/unit test
public abstract ViewStructure newChild(int index, int virtualId, int flags);
@@ -299,7 +289,7 @@ public abstract class ViewStructure {
*
* @param index child index
* @param virtualId id identifying the virtual child inside the custom view.
- * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
+ * @param flags currently {@code 0}.
*/
// TODO(b/33197203, b/33802548): add CTS/unit test
public abstract ViewStructure asyncNewChild(int index, int virtualId, int flags);
@@ -317,12 +307,19 @@ public abstract class ViewStructure {
public abstract void setAutoFillValue(AutoFillValue value);
/**
- * @hide
+ * Marks this node as sanitized so its content are sent on {@link
+ * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+ * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
+ *
+ * <p>Only nodes that does not have PII (Personally Identifiable Information - sensitive data
+ * such as email addresses, credit card numbers, passwords, etc...) should be marked
+ * as sanitized; a good rule of thumb is to mark as sanitized nodes whose value were statically
+ * set from resources.
*
- * TODO(b/33197203, b/33269702): temporary set it as not sanitized until
- * AssistStructure automaticaly sets sanitization based on text coming from resources
+ * <p>Should only be set when the node is used for AutoFill purposes - it will be ignored
+ * when used for Assist.
*/
- public abstract void setSanitized(boolean sensitive);
+ public abstract void setSanitized(boolean sanitized);
/**
* Call when done populating a {@link ViewStructure} returned by
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 67d7ff8da25b..d866927b3dee 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -28,6 +28,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.InputType;
import android.text.Spannable;
+import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AccessibilityClickableSpan;
@@ -2421,7 +2422,7 @@ public class AccessibilityNodeInfo implements Parcelable {
ClickableSpan[] spans =
((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
if (spans.length > 0) {
- Spannable spannable = Spannable.Factory.getInstance().newSpannable(text);
+ Spannable spannable = new SpannableStringBuilder(text);
for (int i = 0; i < spans.length; i++) {
ClickableSpan span = spans[i];
if ((span instanceof AccessibilityClickableSpan)
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index d9003a6fa3bd..2168444b9b58 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -179,8 +179,6 @@ public final class AutoFillManager {
* @param view view whose focus changed.
*/
public void valueChanged(View view) {
- ensureServiceClientAddedIfNeeded();
-
if (!mEnabled || !mHasSession) {
return;
}
@@ -199,8 +197,6 @@ public final class AutoFillManager {
* @param value new value of the child.
*/
public void virtualValueChanged(View parent, int childId, AutoFillValue value) {
- ensureServiceClientAddedIfNeeded();
-
if (!mEnabled || !mHasSession) {
return;
}
@@ -216,8 +212,6 @@ public final class AutoFillManager {
* call this method after the form is submitted and another page is rendered.
*/
public void reset() {
- ensureServiceClientAddedIfNeeded();
-
if (!mEnabled && !mHasSession) {
return;
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 6f687fe5f14c..f2c2af511f81 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -34,6 +34,7 @@ import android.view.ViewDebug;
import android.view.ViewHierarchyEncoder;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.autofill.AutoFillManager;
import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
@@ -164,6 +165,10 @@ public abstract class CompoundButton extends Button implements Checkable {
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
+ final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ if (afm != null) {
+ afm.valueChanged(this);
+ }
mBroadcasting = false;
}
@@ -563,8 +568,6 @@ public abstract class CompoundButton extends Button implements Checkable {
// TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
- // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener
-
@Override
public void autoFill(AutoFillValue value) {
if (!isEnabled()) return;
@@ -579,6 +582,6 @@ public abstract class CompoundButton extends Button implements Checkable {
@Override
public AutoFillValue getAutoFillValue() {
- return isEnabled() ? null : AutoFillValue.forToggle(isChecked());
+ return isEnabled() ? AutoFillValue.forToggle(isChecked()) : null;
}
}
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 919c1e2c4a4c..0f0e6c30979d 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -294,14 +294,15 @@ class DayPickerView extends ViewGroup {
* @param animate whether to smooth scroll to the new position
* @param setSelected whether to set the specified day as selected
*
- * @throws IllegalArgumentException as of {@link android.os.Build.VERSION_CODES#N_MR1} if the
- * provided timeInMillis is before the range start or after the range end.
+ * @throws IllegalArgumentException if the build version is greater than
+ * {@link android.os.Build.VERSION_CODES#N_MR1} and the provided timeInMillis is before
+ * the range start or after the range end.
*/
private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
getTempCalendarForTime(timeInMillis);
final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
- if (targetSdkVersion >= N_MR1) {
+ if (targetSdkVersion > N_MR1) {
if (mTempCalendar.before(mMinDate) || mTempCalendar.after(mMaxDate)) {
throw new IllegalArgumentException("timeInMillis must be between the values of "
+ "getMinDate() and getMaxDate()");
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 8ba4694c331c..76b38131477d 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -24,6 +24,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import android.view.autofill.AutoFillManager;
import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
@@ -177,6 +178,10 @@ public class RadioGroup extends LinearLayout {
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
+ final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ if (afm != null) {
+ afm.valueChanged(this);
+ }
}
private void setCheckedStateForView(int viewId, boolean checked) {
@@ -405,8 +410,6 @@ public class RadioGroup extends LinearLayout {
// TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
- // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener
-
@Override
public void autoFill(AutoFillValue value) {
if (!isEnabled()) return;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 051ffee677c2..9e911632910e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -63,7 +63,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelableParcel;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.provider.Settings;
import android.text.BoringLayout;
import android.text.DynamicLayout;
@@ -727,8 +726,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// mAutoSizeStepGranularityInPx.
private boolean mHasPresetAutoSizeValues = false;
- // Watcher used to notify changes to auto-fill manager.
- private AutoFillChangeWatcher mAutoFillChangeWatcher;
+ // Indicates whether the text was set from resources or dynamically, so it can be used to
+ // sanitize auto-fill request.
+ private boolean mTextFromResource = false;
/**
* Kick-start the font cache for the zygote process (to pay the cost of
@@ -948,6 +948,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes);
int n = a.getIndexCount();
+
+ boolean fromResourceId = false;
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
@@ -1089,6 +1091,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
break;
case com.android.internal.R.styleable.TextView_text:
+ fromResourceId = true;
text = a.getText(attr);
break;
@@ -1567,6 +1570,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
setText(text, bufferType);
+ if (fromResourceId) {
+ mTextFromResource = true;
+ }
+
if (hint != null) setHint(hint);
/*
@@ -5067,6 +5074,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private void setText(CharSequence text, BufferType type,
boolean notifyBefore, int oldlen) {
+ mTextFromResource = false;
if (text == null) {
text = "";
}
@@ -5301,6 +5309,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@android.view.RemotableViewMethod
public final void setText(@StringRes int resid) {
setText(getContext().getResources().getText(resid));
+ mTextFromResource = true;
}
/**
@@ -5327,6 +5336,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
public final void setText(@StringRes int resid, BufferType type) {
setText(getContext().getResources().getText(resid), type);
+ mTextFromResource = true;
}
/**
@@ -9099,6 +9109,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
list.get(i).afterTextChanged(text);
}
}
+
+ // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
+ final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ if (afm != null) {
+ if (DEBUG_AUTOFILL) {
+ Log.v(LOG_TAG, "sendAfterTextChanged(): notify AFM for text=" + text);
+ }
+ afm.valueChanged(TextView.this);
+ }
+
hideErrorIfUnchanged();
}
@@ -9840,16 +9860,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- /**
- * @return true if the user has explicitly allowed accessibility services
- * to speak passwords.
- */
- private boolean shouldSpeakPasswordsForAccessibility() {
- return (Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
- UserHandle.USER_CURRENT_OR_SELF) == 1);
- }
-
@Override
public CharSequence getAccessibilityClassName() {
return TextView.class.getName();
@@ -9872,14 +9882,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
if (forAutoFill) {
- // TODO(b/33197203, b/33269702): temporary set it as not sanitized until
- // AssistStructure automaticaly sets sanitization based on text coming from resources
- structure.setSanitized(!isPassword);
- if (mAutoFillChangeWatcher == null && isTextEditable()) {
- mAutoFillChangeWatcher = new AutoFillChangeWatcher();
- addTextChangedListener(mAutoFillChangeWatcher);
- // TODO(b/33197203): remove mAutoFillValueListener auto-fill session is finished
- }
+ structure.setSanitized(mTextFromResource);
}
if (!isPassword || forAutoFill) {
@@ -10424,13 +10427,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mHint;
}
- // Check whether we need to bypass the transformation
- // method and expose unobscured text.
- if (hasPasswordTransformationMethod() && shouldSpeakPasswordsForAccessibility()) {
- return mText;
- }
-
- // Otherwise, speak whatever text is being displayed.
+ // Otherwise, return whatever text is being displayed.
return mTransformed;
}
@@ -11512,30 +11509,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- // TODO(b/33197203): implements SpanWatcher too?
- private final class AutoFillChangeWatcher implements TextWatcher {
-
- private final AutoFillManager mAfm = mContext.getSystemService(AutoFillManager.class);
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (mAfm != null) {
- if (DEBUG_AUTOFILL) {
- Log.v(LOG_TAG, "AutoFillChangeWatcher.afterTextChanged(): s=" + s);
- }
- mAfm.valueChanged(TextView.this);
- }
- }
- }
-
private class ChangeWatcher implements TextWatcher, SpanWatcher {
private CharSequence mBeforeText;
@@ -11547,9 +11520,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
+ " before=" + before + " after=" + after + ": " + buffer);
}
- if (AccessibilityManager.getInstance(mContext).isEnabled()
- && ((!isPasswordInputType(getInputType()) && !hasPasswordTransformationMethod())
- || shouldSpeakPasswordsForAccessibility())) {
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
mBeforeText = buffer.toString();
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 4ba19f446b13..ae2e0ac88b39 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -1489,21 +1489,10 @@ public class LockPatternView extends View {
return bounds;
}
- private boolean shouldSpeakPassword() {
- final boolean speakPassword = Settings.Secure.getIntForUser(
- mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
- UserHandle.USER_CURRENT_OR_SELF) != 0;
- final boolean hasHeadphones = mAudioManager != null ?
- (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn())
- : false;
- return speakPassword || hasHeadphones;
- }
-
private CharSequence getTextForVirtualView(int virtualViewId) {
final Resources res = getResources();
- return shouldSpeakPassword() ? res.getString(
- R.string.lockscreen_access_pattern_cell_added_verbose, virtualViewId)
- : res.getString(R.string.lockscreen_access_pattern_cell_added);
+ return res.getString(R.string.lockscreen_access_pattern_cell_added_verbose,
+ virtualViewId);
}
/**