diff options
13 files changed, 139 insertions, 26 deletions
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index e7e539c7f01c..cbe75c405fe4 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -154,6 +154,10 @@ public class WebViewClient { * other than the UI thread so clients should exercise caution * when accessing private data or the view system. * + * <p>Note: when Safe Browsing is enabled, these URLs still undergo Safe Browsing checks. If + * this is undesired, whitelist the URL with {@link WebView#setSafeBrowsingWhitelist} or ignore + * the warning with {@link #onSafeBrowsingHit}. + * * @param view The {@link android.webkit.WebView} that is requesting the * resource. * @param url The raw url of the resource. @@ -177,6 +181,10 @@ public class WebViewClient { * other than the UI thread so clients should exercise caution * when accessing private data or the view system. * + * <p>Note: when Safe Browsing is enabled, these URLs still undergo Safe Browsing checks. If + * this is undesired, whitelist the URL with {@link WebView#setSafeBrowsingWhitelist} or ignore + * the warning with {@link #onSafeBrowsingHit}. + * * @param view The {@link android.webkit.WebView} that is requesting the * resource. * @param request Object containing the details of the request. diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 31d878f7a50b..f1f25bf82b7f 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1250,7 +1250,8 @@ public class Editor { } } - void sendOnTextChanged(int start, int after) { + void sendOnTextChanged(int start, int before, int after) { + getSelectionActionModeHelper().onTextChanged(start, start + before); updateSpellCheckSpans(start, start + after, false); // Flip flag to indicate the word iterator needs to have the text reset. diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index aafa343fc96c..4ebb3cfea266 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -122,10 +122,8 @@ final class SelectionActionModeHelper { SelectionEvent.ActionType.DRAG, mTextClassification); } - public void onTypeOverSelection() { - mSelectionTracker.onSelectionAction( - mTextView.getSelectionStart(), mTextView.getSelectionEnd(), - SelectionEvent.ActionType.OVERTYPE, mTextClassification); + public void onTextChanged(int start, int end) { + mSelectionTracker.onTextChanged(start, end, mTextClassification); } public boolean resetSelection(int textIndex) { @@ -217,7 +215,6 @@ final class SelectionActionModeHelper { private int mOriginalEnd; private int mSelectionStart; private int mSelectionEnd; - private boolean mSelectionStarted; private boolean mAllowReset; SelectionTracker(TextView textView) { @@ -230,9 +227,8 @@ final class SelectionActionModeHelper { */ public void onOriginalSelection( CharSequence text, int selectionStart, int selectionEnd, boolean editableText) { - mOriginalStart = selectionStart; - mOriginalEnd = selectionEnd; - mSelectionStarted = true; + mOriginalStart = mSelectionStart = selectionStart; + mOriginalEnd = mSelectionEnd = selectionEnd; mAllowReset = false; maybeInvalidateLogger(); mLogger.logSelectionStarted(text, selectionStart); @@ -242,7 +238,7 @@ final class SelectionActionModeHelper { * Called when selection action mode is started and the results come from a classifier. */ public void onSmartSelection(SelectionResult result) { - if (mSelectionStarted) { + if (isSelectionStarted()) { mSelectionStart = result.mStart; mSelectionEnd = result.mEnd; mAllowReset = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd; @@ -257,7 +253,9 @@ final class SelectionActionModeHelper { public void onSelectionUpdated( int selectionStart, int selectionEnd, @Nullable TextClassification classification) { - if (mSelectionStarted) { + if (isSelectionStarted()) { + mSelectionStart = selectionStart; + mSelectionEnd = selectionEnd; mAllowReset = false; mLogger.logSelectionModified(selectionStart, selectionEnd, classification, null); } @@ -268,10 +266,13 @@ final class SelectionActionModeHelper { */ public void onSelectionDestroyed() { mAllowReset = false; - mSelectionStarted = false; - mLogger.logSelectionAction( - mSelectionStart, mSelectionEnd, - SelectionEvent.ActionType.ABANDON, null /* classification */); + // Wait a few ms to see if the selection was destroyed because of a text change event. + mTextView.postDelayed(() -> { + mLogger.logSelectionAction( + mSelectionStart, mSelectionEnd, + SelectionEvent.ActionType.ABANDON, null /* classification */); + mSelectionStart = mSelectionEnd = -1; + }, 100 /* ms */); } /** @@ -281,7 +282,7 @@ final class SelectionActionModeHelper { int selectionStart, int selectionEnd, @SelectionEvent.ActionType int action, @Nullable TextClassification classification) { - if (mSelectionStarted) { + if (isSelectionStarted()) { mAllowReset = false; mLogger.logSelectionAction(selectionStart, selectionEnd, action, classification); } @@ -295,13 +296,15 @@ final class SelectionActionModeHelper { */ public boolean resetSelection(int textIndex, Editor editor) { final TextView textView = editor.getTextView(); - if (mSelectionStarted + if (isSelectionStarted() && mAllowReset && textIndex >= mSelectionStart && textIndex <= mSelectionEnd && textView.getText() instanceof Spannable) { mAllowReset = false; boolean selected = editor.selectCurrentWord(); if (selected) { + mSelectionStart = editor.getTextView().getSelectionStart(); + mSelectionEnd = editor.getTextView().getSelectionEnd(); mLogger.logSelectionAction( textView.getSelectionStart(), textView.getSelectionEnd(), SelectionEvent.ActionType.RESET, null /* classification */); @@ -311,11 +314,21 @@ final class SelectionActionModeHelper { return false; } + public void onTextChanged(int start, int end, TextClassification classification) { + if (isSelectionStarted() && start == mSelectionStart && end == mSelectionEnd) { + onSelectionAction(start, end, SelectionEvent.ActionType.OVERTYPE, classification); + } + } + private void maybeInvalidateLogger() { if (mLogger.isEditTextLogger() != mTextView.isTextEditable()) { mLogger = new SelectionMetricsLogger(mTextView); } } + + private boolean isSelectionStarted() { + return mSelectionStart >= 0 && mSelectionEnd >= 0 && mSelectionStart != mSelectionEnd; + } } // TODO: Write tests diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index cd2d2fdf5a8a..11fe67c0564c 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -9364,7 +9364,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - if (mEditor != null) mEditor.sendOnTextChanged(start, after); + if (mEditor != null) mEditor.sendOnTextChanged(start, before, after); } /** diff --git a/core/res/res/drawable/ic_close.xml b/core/res/res/drawable/ic_close.xml index 708695994ab6..70565f296a1f 100644 --- a/core/res/res/drawable/ic_close.xml +++ b/core/res/res/drawable/ic_close.xml @@ -19,6 +19,6 @@ Copyright (C) 2016 The Android Open Source Project android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z" + android:pathData="M18.3,5.71a0.996,0.996 0,0 0,-1.41 0L12,10.59 7.11,5.7A0.996,0.996 0,1 0,5.7 7.11L10.59,12 5.7,16.89a0.996,0.996 0,1 0,1.41 1.41L12,13.41l4.89,4.89a0.996,0.996 0,1 0,1.41 -1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z" android:fillColor="#FF000000"/> </vector> diff --git a/core/res/res/drawable/ic_eject_24dp.xml b/core/res/res/drawable/ic_eject_24dp.xml index 1bb351a57601..321ee3b6289c 100644 --- a/core/res/res/drawable/ic_eject_24dp.xml +++ b/core/res/res/drawable/ic_eject_24dp.xml @@ -20,5 +20,8 @@ Copyright (C) 2015 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#FF000000" - android:pathData="M5 17h14v2H5zm7,-12L5.33 15h13.34z"/> + android:pathData="M6,17h12c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H6c-0.55,0 -1,-0.45 -1,-1v0C5,17.45 5.45,17 6,17z"/> + <path + android:fillColor="#FF000000" + android:pathData="M11.1,5.48l-5.22,7.83C5.39,14.03 5.91,15 6.78,15h10.44c0.87,0 1.39,-0.97 0.9,-1.69L12.9,5.48C12.47,4.84 11.53,4.84 11.1,5.48z"/> </vector> diff --git a/core/res/res/drawable/ic_feedback.xml b/core/res/res/drawable/ic_feedback.xml index 365863da31e2..c316e7df5d4b 100644 --- a/core/res/res/drawable/ic_feedback.xml +++ b/core/res/res/drawable/ic_feedback.xml @@ -20,5 +20,5 @@ Copyright (C) 2016 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#FF000000" - android:pathData="M20.0,2.0L4.0,2.0c-1.1,0.0 -1.9,0.9 -1.99,2.0L2.0,22.0l4.0,-4.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L22.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0l0.0,2.0zm0.0,-4.0l-2.0,0.0L11.0,6.0l2.0,0.0l0.0,4.0z"/> + android:pathData="M20,2H4C2.9,2 2,2.9 2,4v17.39c0,0.54 0.65,0.81 1.04,0.43L6.86,18H20c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2zM11,7c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v3c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V7zM12,15.2c-0.61,0 -1.1,-0.49 -1.1,-1.1c0,-0.61 0.49,-1.1 1.1,-1.1c0.61,0 1.1,0.49 1.1,1.1C13.1,14.71 12.61,15.2 12,15.2z"/> </vector> diff --git a/core/res/res/drawable/ic_refresh.xml b/core/res/res/drawable/ic_refresh.xml index 1297407fbb8b..5894f9526ec2 100644 --- a/core/res/res/drawable/ic_refresh.xml +++ b/core/res/res/drawable/ic_refresh.xml @@ -20,5 +20,5 @@ Copyright (C) 2016 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#FF000000" - android:pathData="M17.65,6.35C16.2,4.9 14.21,4.0 12.0,4.0c-4.42,0.0 -7.99,3.58 -7.99,8.0s3.57,8.0 7.99,8.0c3.73,0.0 6.84,-2.55 7.73,-6.0l-2.08,0.0c-0.82,2.33 -3.04,4.0 -5.65,4.0 -3.31,0.0 -6.0,-2.69 -6.0,-6.0s2.69,-6.0 6.0,-6.0c1.66,0.0 3.1,0.69 4.22,1.78L13.0,11.0l7.0,0.0L20.0,4.0l-2.35,2.35z"/> + android:pathData="M17.65,6.35c-1.63,-1.63 -3.94,-2.57 -6.48,-2.31c-3.67,0.37 -6.69,3.35 -7.1,7.02C3.52,15.91 7.27,20 12,20c3.19,0 5.93,-1.87 7.21,-4.57c0.31,-0.66 -0.16,-1.43 -0.89,-1.43h-0.01c-0.37,0 -0.72,0.2 -0.88,0.53c-1.13,2.43 -3.84,3.97 -6.81,3.32c-2.22,-0.49 -4.01,-2.3 -4.49,-4.52C5.31,9.44 8.26,6 12,6c1.66,0 3.14,0.69 4.22,1.78l-2.37,2.37C13.54,10.46 13.76,11 14.21,11H19c0.55,0 1,-0.45 1,-1V5.21c0,-0.45 -0.54,-0.67 -0.85,-0.35L17.65,6.35z"/> </vector> diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index ccf9de0abdb4..7e959a87da5d 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -754,6 +754,8 @@ public class KeyStore { // None of the key's SIDs can ever be authenticated return new KeyPermanentlyInvalidatedException(); } + case UNINITIALIZED: + return new KeyPermanentlyInvalidatedException(); default: return new InvalidKeyException("Keystore operation failed", e); } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java index cb15a795fe9b..1286d57b4959 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java @@ -33,7 +33,7 @@ class TimestampedScoredNetwork implements Parcelable { } protected TimestampedScoredNetwork(Parcel in) { - mScore = ScoredNetwork.CREATOR.createFromParcel(in); + mScore = in.readParcelable(ScoredNetwork.class.getClassLoader()); mUpdatedTimestampMillis = in.readLong(); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java new file mode 100644 index 000000000000..639d51c61f2c --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.settingslib.wifi; + +import static com.google.common.truth.Truth.assertThat; + +import android.net.NetworkKey; +import android.net.ScoredNetwork; +import android.net.WifiKey; +import android.os.Parcel; + +import com.android.settingslib.SettingLibRobolectricTestRunner; +import com.android.settingslib.TestConfig; +import java.util.Date; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingLibRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TimestampedScoredNetworkTest { + private TimestampedScoredNetwork impl; + + private ScoredNetwork createTestScoredNetwork(String ssid) { + return new ScoredNetwork( + new NetworkKey(new WifiKey("\"" + ssid + "\"", "00:00:00:00:00:00")), null); + } + + @Before + public void setUp() { + impl = new TimestampedScoredNetwork(createTestScoredNetwork("test"), + 0 /* updatedTimestampMillis */); + } + + @Test + public void testUpdate() { + long time = new Date().getTime(); + ScoredNetwork updated = createTestScoredNetwork("updated"); + impl.update(updated, time); + + assertThat(impl.getScore()).isEqualTo(updated); + assertThat(impl.getUpdatedTimestampMillis()).isEqualTo(time); + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + impl.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + TimestampedScoredNetwork fromParcel = TimestampedScoredNetwork.CREATOR.createFromParcel(parcel); + + assertThat(fromParcel.getScore()).isEqualTo(impl.getScore()); + assertThat(fromParcel.getUpdatedTimestampMillis()).isEqualTo(impl.getUpdatedTimestampMillis()); + } +} diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f1ea85374db3..e70a294d4684 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4649,7 +4649,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Ignore updates for disconnected networks return; } - + // newLp is already a defensive copy. + newLp.ensureDirectlyConnectedRoutes(); if (VDBG) { log("Update of LinkProperties for " + nai.name() + "; created=" + nai.created + @@ -4659,8 +4660,6 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (nai) { nai.linkProperties = newLp; } - // msg.obj is already a defensive copy. - nai.linkProperties.ensureDirectlyConnectedRoutes(); if (nai.everConnected) { updateLinkProperties(nai, oldLp); } diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 1082eae7df84..a3811baf2657 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -18,6 +18,7 @@ package com.android.server.pm; import android.Manifest; import android.annotation.NonNull; +import android.app.ActivityManager; import android.app.DownloadManager; import android.app.admin.DevicePolicyManager; import android.companion.CompanionDeviceManager; @@ -582,6 +583,21 @@ final class DefaultPermissionGrantPolicy { } } + if (ActivityManager.isLowRamDeviceStatic()) { + // Allow voice search on low-ram devices + Intent globalSearchIntent = new Intent("android.search.action.GLOBAL_SEARCH"); + PackageParser.Package globalSearchPickerPackage = + getDefaultSystemHandlerActivityPackageLPr(globalSearchIntent, userId); + + if (globalSearchPickerPackage != null + && doesPackageSupportRuntimePermissions(globalSearchPickerPackage)) { + grantRuntimePermissionsLPw(globalSearchPickerPackage, + MICROPHONE_PERMISSIONS, true, userId); + grantRuntimePermissionsLPw(globalSearchPickerPackage, + LOCATION_PERMISSIONS, true, userId); + } + } + // Voice recognition Intent voiceRecoIntent = new Intent("android.speech.RecognitionService"); voiceRecoIntent.addCategory(Intent.CATEGORY_DEFAULT); |