Merge "Added getDataPreloadsMediaDirectory" into nyc-dr1-dev
am: 0a376f5619
Change-Id: I114f0b42e75d2aa9a288334999b7d44f0830a2d3
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 27b0a8b..5099eeb 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -30,7 +30,6 @@
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
-
import java.util.List;
/**
@@ -123,22 +122,36 @@
"android.intent.action.VOICEMAIL_SMS_RECEIVED";
/**
- * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate the
- * event type of the SMS. Common values are "SYNC" or "STATUS"
+ * Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to
+ * indicate the event type of the SMS. Common values are "SYNC" or "STATUS". The extra will not
+ * exist if the framework cannot parse the SMS as voicemail but the carrier pattern indicates
+ * it is.
*/
/** @hide */
public static final String EXTRA_VOICEMAIL_SMS_PREFIX =
"com.android.voicemail.extra.VOICEMAIL_SMS_PREFIX";
/**
- * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate the
- * fields sent by the SMS
+ * Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to
+ * indicate the fields sent by the SMS. The extra will not exist if the framework cannot
+ * parse the SMS as voicemail but the carrier pattern indicates it is.
*/
/** @hide */
public static final String EXTRA_VOICEMAIL_SMS_FIELDS =
"com.android.voicemail.extra.VOICEMAIL_SMS_FIELDS";
/**
+ * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate the
+ * message body of the SMS. This extra is included if the framework cannot
+ * parse the SMS as voicemail but the carrier pattern indicates it is.
+ */
+ /**
+ * @hide
+ */
+ public static final String EXTRA_VOICEMAIL_SMS_MESSAGE_BODY =
+ "com.android.voicemail.extra.VOICEMAIL_SMS_MESSAGE_BODY";
+
+ /**
* Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate he
* subscription ID of the phone account that received the SMS.
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 872168a..20c15a49 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20280,8 +20280,14 @@
// remove it from the transparent region.
final int[] location = attachInfo.mTransparentLocation;
getLocationInWindow(location);
- region.op(location[0], location[1], location[0] + mRight - mLeft,
- location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
+ // When a view has Z value, then it will be better to leave some area below the view
+ // for drawing shadow. The shadow outset is proportional to the Z value. Note that
+ // the bottom part needs more offset than the left, top and right parts due to the
+ // spot light effects.
+ int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
+ region.op(location[0] - shadowOffset, location[1] - shadowOffset,
+ location[0] + mRight - mLeft + shadowOffset,
+ location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
} else {
if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
// The SKIP_DRAW flag IS set and the background drawable exists, we remove
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3ff8d4f..6933efc15 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -6406,16 +6406,28 @@
return true;
}
super.gatherTransparentRegion(region);
- final View[] children = mChildren;
- final int count = mChildrenCount;
+ // Instead of naively traversing the view tree, we have to traverse according to the Z
+ // order here. We need to go with the same order as dispatchDraw().
+ // One example is that after surfaceView punch a hole, we will still allow other views drawn
+ // on top of that hole. In this case, those other views should be able to cut the
+ // transparent region into smaller area.
+ final int childrenCount = mChildrenCount;
boolean noneOfTheChildrenAreTransparent = true;
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
- if (!child.gatherTransparentRegion(region)) {
- noneOfTheChildrenAreTransparent = false;
+ if (childrenCount > 0) {
+ final ArrayList<View> preorderedList = buildOrderedChildList();
+ final boolean customOrder = preorderedList == null
+ && isChildrenDrawingOrderEnabled();
+ final View[] children = mChildren;
+ for (int i = 0; i < childrenCount; i++) {
+ final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
+ if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
+ if (!child.gatherTransparentRegion(region)) {
+ noneOfTheChildrenAreTransparent = false;
+ }
}
}
+ if (preorderedList != null) preorderedList.clear();
}
return meOpaque || noneOfTheChildrenAreTransparent;
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 2dfa8cd..44f6fac 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.Handler;
@@ -91,6 +92,9 @@
/** @hide */
public static final int AUTOCLICK_DELAY_DEFAULT = 600;
+ /** @hide */
+ public static final int MAX_A11Y_EVENTS_PER_SERVICE_CALL = 20;
+
static final Object sInstanceSync = new Object();
private static AccessibilityManager sInstance;
@@ -99,6 +103,8 @@
private IAccessibilityManager mService;
+ private EventDispatchThread mEventDispatchThread;
+
final int mUserId;
final Handler mHandler;
@@ -170,7 +176,7 @@
private final IAccessibilityManagerClient.Stub mClient =
new IAccessibilityManagerClient.Stub() {
public void setState(int state) {
- // We do not want to change this immediately as the applicatoin may
+ // We do not want to change this immediately as the application may
// have already checked that accessibility is on and fired an event,
// that is now propagating up the view tree, Hence, if accessibility
// is now off an exception will be thrown. We want to have the exception
@@ -297,47 +303,32 @@
* their descendants.
*/
public void sendAccessibilityEvent(AccessibilityEvent event) {
- final IAccessibilityManager service;
- final int userId;
- synchronized (mLock) {
- service = getServiceLocked();
- if (service == null) {
+ if (!isEnabled()) {
+ Looper myLooper = Looper.myLooper();
+ if (myLooper == Looper.getMainLooper()) {
+ throw new IllegalStateException(
+ "Accessibility off. Did you forget to check that?");
+ } else {
+ // If we're not running on the thread with the main looper, it's possible for
+ // the state of accessibility to change between checking isEnabled and
+ // calling this method. So just log the error rather than throwing the
+ // exception.
+ Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled");
return;
}
- if (!mIsEnabled) {
- Looper myLooper = Looper.myLooper();
- if (myLooper == Looper.getMainLooper()) {
- throw new IllegalStateException(
- "Accessibility off. Did you forget to check that?");
- } else {
- // If we're not running on the thread with the main looper, it's possible for
- // the state of accessibility to change between checking isEnabled and
- // calling this method. So just log the error rather than throwing the
- // exception.
- Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled");
- return;
- }
- }
- userId = mUserId;
}
- boolean doRecycle = false;
- try {
- event.setEventTime(SystemClock.uptimeMillis());
- // it is possible that this manager is in the same process as the service but
- // client using it is called through Binder from another process. Example: MMS
- // app adds a SMS notification and the NotificationManagerService calls this method
- long identityToken = Binder.clearCallingIdentity();
- doRecycle = service.sendAccessibilityEvent(event, userId);
- Binder.restoreCallingIdentity(identityToken);
- if (DEBUG) {
- Log.i(LOG_TAG, event + " sent");
+ event.setEventTime(SystemClock.uptimeMillis());
+
+ getEventDispatchThread().scheduleEvent(event);
+ }
+
+ private EventDispatchThread getEventDispatchThread() {
+ synchronized (mLock) {
+ if (mEventDispatchThread == null) {
+ mEventDispatchThread = new EventDispatchThread(mService, mUserId);
+ mEventDispatchThread.start();
}
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error during sending " + event + " ", re);
- } finally {
- if (doRecycle) {
- event.recycle();
- }
+ return mEventDispatchThread;
}
}
@@ -620,7 +611,7 @@
}
}
- private IAccessibilityManager getServiceLocked() {
+ private IAccessibilityManager getServiceLocked() {
if (mService == null) {
tryConnectToServiceLocked(null);
}
@@ -722,4 +713,99 @@
}
}
}
+
+ private static class EventDispatchThread extends Thread {
+ // Second lock used to keep UI thread performant. Never try to grab mLock when holding
+ // this one, or the UI thread will block in send AccessibilityEvent.
+ private final Object mEventQueueLock = new Object();
+
+ // Two lists to hold events. The app thread fills one while we empty the other.
+ private final ArrayList<AccessibilityEvent> mEventLists0 =
+ new ArrayList<>(MAX_A11Y_EVENTS_PER_SERVICE_CALL);
+ private final ArrayList<AccessibilityEvent> mEventLists1 =
+ new ArrayList<>(MAX_A11Y_EVENTS_PER_SERVICE_CALL);
+
+ private boolean mPingPongListToggle;
+
+ private final IAccessibilityManager mService;
+
+ private final int mUserId;
+
+ EventDispatchThread(IAccessibilityManager service, int userId) {
+ mService = service;
+ mUserId = userId;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ ArrayList<AccessibilityEvent> listBeingDrained;
+ synchronized (mEventQueueLock) {
+ ArrayList<AccessibilityEvent> listBeingFilled = getListBeingFilledLocked();
+ if (listBeingFilled.isEmpty()) {
+ try {
+ mEventQueueLock.wait();
+ } catch (InterruptedException e) {
+ // Treat as a notify
+ }
+ }
+ // Swap buffers
+ mPingPongListToggle = !mPingPongListToggle;
+ listBeingDrained = listBeingFilled;
+ }
+ dispatchEvents(listBeingDrained);
+ }
+ }
+
+ public void scheduleEvent(AccessibilityEvent event) {
+ synchronized (mEventQueueLock) {
+ getListBeingFilledLocked().add(event);
+ mEventQueueLock.notifyAll();
+ }
+ }
+
+ private ArrayList<AccessibilityEvent> getListBeingFilledLocked() {
+ return (mPingPongListToggle) ? mEventLists0 : mEventLists1;
+ }
+
+ private void dispatchEvents(ArrayList<AccessibilityEvent> events) {
+ int eventListCapacityLowerBound = events.size();
+ while (events.size() > 0) {
+ // We don't want to consume extra memory if an app sends a lot of events in a
+ // one-off event. Cap the list length at double the max events per call.
+ // We'll end up with extra GC for apps that send huge numbers of events, but
+ // sending that many events will lead to bad performance in any case.
+ if ((eventListCapacityLowerBound > 2 * MAX_A11Y_EVENTS_PER_SERVICE_CALL)
+ && (events.size() <= 2 * MAX_A11Y_EVENTS_PER_SERVICE_CALL)) {
+ events.trimToSize();
+ eventListCapacityLowerBound = events.size();
+ }
+ // We only expect this loop to run once, as the app shouldn't be sending
+ // huge numbers of events.
+ // The clear in the called method will remove the sent events
+ dispatchOneBatchOfEvents(events.subList(0,
+ Math.min(events.size(), MAX_A11Y_EVENTS_PER_SERVICE_CALL)));
+ }
+ }
+
+ private void dispatchOneBatchOfEvents(List<AccessibilityEvent> events) {
+ if (events.isEmpty()) {
+ return;
+ }
+ long identityToken = Binder.clearCallingIdentity();
+ try {
+ mService.sendAccessibilityEvents(new ParceledListSlice<>(events),
+ mUserId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error sending multiple events");
+ }
+ Binder.restoreCallingIdentity(identityToken);
+ if (DEBUG) {
+ Log.i(LOG_TAG, events.size() + " events sent");
+ }
+ for (int i = events.size() - 1; i >= 0; i--) {
+ events.remove(i).recycle();
+ }
+ }
+ }
}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 7f44bac..aa9cb39 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -21,6 +21,7 @@
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.content.ComponentName;
+import android.content.pm.ParceledListSlice;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -37,7 +38,9 @@
int addClient(IAccessibilityManagerClient client, int userId);
- boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
+ void sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
+
+ void sendAccessibilityEvents(in ParceledListSlice events, int userId);
List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 6432f70..5935c78 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1547,7 +1547,7 @@
}
// Let the window manager know to align the top to y.
- outParams.gravity = Gravity.LEFT | Gravity.TOP;
+ outParams.gravity = computeGravity();
outParams.width = width;
outParams.height = height;
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index d2d39cd..0468b64 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -52,11 +52,9 @@
} gRectClassInfo;
// Also used in PdfRenderer.cpp
-Mutex sPdfiumLock;
int sUnmatchedPdfiumInitRequestCount = 0;
static void initializeLibraryIfNeeded() {
- Mutex::Autolock _l(sPdfiumLock);
if (sUnmatchedPdfiumInitRequestCount == 0) {
FPDF_InitLibrary();
}
@@ -64,7 +62,6 @@
}
static void destroyLibraryIfNeeded() {
- Mutex::Autolock _l(sPdfiumLock);
sUnmatchedPdfiumInitRequestCount--;
if (sUnmatchedPdfiumInitRequestCount == 0) {
FPDF_DestroyLibrary();
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index 71bec78..43550ac 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -44,11 +44,9 @@
} gPointClassInfo;
// See PdfEditor.cpp
-extern Mutex sPdfiumLock;
extern int sUnmatchedPdfiumInitRequestCount;
static void initializeLibraryIfNeeded() {
- Mutex::Autolock _l(sPdfiumLock);
if (sUnmatchedPdfiumInitRequestCount == 0) {
FPDF_InitLibrary();
}
@@ -56,7 +54,6 @@
}
static void destroyLibraryIfNeeded() {
- Mutex::Autolock _l(sPdfiumLock);
sUnmatchedPdfiumInitRequestCount--;
if (sUnmatchedPdfiumInitRequestCount == 0) {
FPDF_DestroyLibrary();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ed71fc2f..3339d02 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -183,6 +183,7 @@
<protected-broadcast
android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
<protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
<protected-broadcast android:name="android.btopp.intent.action.LIST" />
@@ -199,6 +200,8 @@
<protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authcancelled" />
+ <protected-broadcast android:name="com.android.bluetooth.sap.USER_CONFIRM_TIMEOUT" />
+ <protected-broadcast android:name="com.android.bluetooth.sap.action.DISCONNECT_ACTION" />
<protected-broadcast android:name="android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED" />
@@ -394,6 +397,8 @@
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
<protected-broadcast android:name="com.android.bluetooth.map.USER_CONFIRM_TIMEOUT" />
+ <protected-broadcast android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
+ <protected-broadcast android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
<protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
<protected-broadcast android:name="android.content.syncmanager.SYNC_ALARM" />
<protected-broadcast android:name="android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION" />
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 8023edf..350caaa 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -598,7 +598,7 @@
<string name="phoneTypeCallback" msgid="2712175203065678206">"Devolver chamada"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Coche"</string>
<string name="phoneTypeCompanyMain" msgid="540434356461478916">"Empresa (ppal.)"</string>
- <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
+ <string name="phoneTypeIsdn" msgid="8022453193171370337">"RDSI"</string>
<string name="phoneTypeMain" msgid="6766137010628326916">"Principal"</string>
<string name="phoneTypeOtherFax" msgid="8587657145072446565">"Outro fax"</string>
<string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index bebe027..10c5836 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1362,7 +1362,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"אפשרויות נוספות"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="3570990907910199483">"אחסון משותף פנימי"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"אחסון שיתוף פנימי"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"כרטיס SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"כרטיס SD של <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"כונן USB"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5b446b4..8bd7160 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1310,7 +1310,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"옵션 더보기"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="3570990907910199483">"내부 공유 저장공간"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"내부 공유 저장용량"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD 카드"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 카드"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB 드라이브"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 0f82dcb..58c2c8a 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1197,8 +1197,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Колдонмого орнотуу сеанстарын окуу мүмкүнчүлүгүн берет. Ушуну менен, ал жигердүү топтом орнотууларынын чоо-жайын көрө алат."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"орнотуу топтомдорун суроо"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Колдонмо топтомдорду орнотууга уруксат сурай алат."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Масштабдын параметрлерин өзгөртүү үчүн бул жерди эки жолу басыңыз."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджетти кошуу мүмкүн болбоду."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Өтүү"</string>
<string name="ime_action_search" msgid="658110271822807811">"Издөө"</string>
@@ -1229,10 +1228,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Эскертмелердин маанилүүлүгүн баалоо кызматы"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN иштетилди"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> аркылуу жандырылды"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Тармактын параметрлерин өзгөртүү үчүн бул жерди басыңыз."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> сеансына туташуу ишке ашты. Желенин параметрлерин өзгөртүү үчүн бул жерди басыңыз."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Дайым иштеген VPN туташууда…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Дайым иштеген VPN туташтырылды"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Дайым иштеген VPN\'де ката кетти"</string>
diff --git a/core/res/res/values-mcc222-mnc10/config.xml b/core/res/res/values-mcc222-mnc10/config.xml
index cd6e8c6..c819de2 100644
--- a/core/res/res/values-mcc222-mnc10/config.xml
+++ b/core/res/res/values-mcc222-mnc10/config.xml
@@ -28,29 +28,4 @@
<string-array translatable="false" name="config_tether_apndata">
<item>Tethering Internet,web.omnitel.it,,,,,,,,,222,10,,DUN</item>
</string-array>
-
- <string-array translatable="false" name="config_operatorConsideredNonRoaming">
- <item>21401</item>
- <item>21402</item>
- <item>21403</item>
- <item>21404</item>
- <item>21405</item>
- <item>21406</item>
- <item>21407</item>
- <item>21408</item>
- <item>21409</item>
- <item>21410</item>
- <item>21411</item>
- <item>21412</item>
- <item>21413</item>
- <item>21414</item>
- <item>21415</item>
- <item>21416</item>
- <item>21417</item>
- <item>21418</item>
- <item>21419</item>
- <item>21420</item>
- <item>21421</item>
- </string-array>
-
</resources>
diff --git a/core/res/res/values-mcc232-mnc10/config.xml b/core/res/res/values-mcc232-mnc10/config.xml
new file mode 100644
index 0000000..bdf83016
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc10/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 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.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23203</item>
+ <item>23205</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc13/config.xml b/core/res/res/values-mcc232-mnc13/config.xml
new file mode 100644
index 0000000..2c14f87
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc13/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 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.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23203</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc500/config.xml b/core/res/res/values-mcc302-mnc500/config.xml
new file mode 100644
index 0000000..77f6419
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc500/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 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.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc510/config.xml b/core/res/res/values-mcc302-mnc510/config.xml
new file mode 100644
index 0000000..77f6419
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc510/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 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.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ae115d8..5a356d5 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1310,7 +1310,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="3570990907910199483">"Armazenamento interno partilhado"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Armazen. interno partilhado"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unidade USB"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e21925b..82c9300 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2519,4 +2519,13 @@
Note: Also update appropriate overlay files. -->
<string-array translatable="false" name="config_defaultFirstUserRestrictions">
</string-array>
+
+ <!-- A array of regex to treat a SMS as VVM SMS if the message body matches.
+ Each item represents an entry, which consists of two parts:
+ a comma (,) separated list of MCCMNC the regex applies to, followed by a semicolon (;), and
+ then the regex itself. -->
+ <string-array translatable="false" name="config_vvmSmsFilterRegexes">
+ <!-- Verizon requires any SMS that starts with //VZWVVM to be treated as a VVM SMS-->
+ <item>310004,310010,310012,310013,310590,310890,310910,311110,311270,311271,311272,311273,311274,311275,311276,311277,311278,311279,311280,311281,311282,311283,311284,311285,311286,311287,311288,311289,311390,311480,311481,311482,311483,311484,311485,311486,311487,311488,311489;^//VZWVVM.*</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c9ed497..b31605d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2266,6 +2266,8 @@
<java-symbol type="string" name="prohibit_manual_network_selection_in_gobal_mode" />
<java-symbol type="id" name="profile_button" />
+ <java-symbol type="array" name="config_vvmSmsFilterRegexes" />
+
<!-- Cascading submenus -->
<java-symbol type="dimen" name="cascading_menus_min_smallest_width" />
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index c836204..0f305f3 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -144,6 +144,55 @@
* android:valueType="pathType"/>
* </set>
* </pre></li>
+ * <p>
+ * Since AAPT tool is now supporting a new format which can bundle several related XML files into
+ * one, we can merge the previous example into one XML file, like this:
+ * </p>
+ * <pre>
+ * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ * <aapt:attr name="android:drawable">
+ * <vector
+ * android:height="64dp"
+ * android:width="64dp"
+ * android:viewportHeight="600"
+ * android:viewportWidth="600" >
+ * <group
+ * android:name="rotationGroup"
+ * android:pivotX="300.0"
+ * android:pivotY="300.0"
+ * android:rotation="45.0" >
+ * <path
+ * android:name="v"
+ * android:fillColor="#000000"
+ * android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
+ * </group>
+ * </vector>
+ * </aapt:attr>
+ *
+ * <target android:name="rotationGroup"> *
+ * <aapt:attr name="android:animation">
+ * <objectAnimator
+ * android:duration="6000"
+ * android:propertyName="rotation"
+ * android:valueFrom="0"
+ * android:valueTo="360" />
+ * </aapt:attr>
+ * </target>
+ *
+ * <target android:name="v" >
+ * <aapt:attr name="android:animation">
+ * <set>
+ * <objectAnimator
+ * android:duration="3000"
+ * android:propertyName="pathData"
+ * android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
+ * android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
+ * android:valueType="pathType"/>
+ * </set>
+ * </aapt:attr>
+ * </target>
+ * </animated-vector>
+ * </pre>
*
* @attr ref android.R.styleable#AnimatedVectorDrawable_drawable
* @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index dc1d18f..9ff6965 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -27,9 +27,9 @@
import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
-import android.graphics.PorterDuff.Mode;
import android.graphics.Shader;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -140,12 +140,16 @@
* in the SVG's path data. This is defined in the viewport space.</dd>
* <dt><code>android:fillColor</code></dt>
* <dd>Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list
- * or a gradient color. If this property is animated, any value set by the animation will
- * override the original value. No path fill is drawn if this property is not specified.</dd>
+ * or a gradient color (See {@link android.R.styleable#GradientColor}
+ * and {@link android.R.styleable#GradientColorItem}).
+ * If this property is animated, any value set by the animation will override the original value.
+ * No path fill is drawn if this property is not specified.</dd>
* <dt><code>android:strokeColor</code></dt>
* <dd>Specifies the color used to draw the path outline. May be a color or, for SDK 24+, a color
- * state list or a gradient color. If this property is animated, any value set by the animation will
- * override the original value. No path outline is drawn if this property is not specified.</dd>
+ * state list or a gradient color (See {@link android.R.styleable#GradientColor}
+ * and {@link android.R.styleable#GradientColorItem}).
+ * If this property is animated, any value set by the animation will override the original value.
+ * No path outline is drawn if this property is not specified.</dd>
* <dt><code>android:strokeWidth</code></dt>
* <dd>The width a path stroke.</dd>
* <dt><code>android:strokeAlpha</code></dt>
@@ -166,8 +170,9 @@
* <dt><code>android:strokeMiterLimit</code></dt>
* <dd>Sets the Miter limit for a stroked path.</dd>
* <dt><code>android:fillType</code></dt>
- * <dd>Sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
- * For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty</dd>
+ * <dd>Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
+ * same as SVG's "fill-rule" properties. For more details, see
+ * <a href="https://www.w3.org/TR/SVG/painting.html#FillRuleProperty">FillRuleProperty</a></dd>
* </dl></dd>
* </dl>
*
@@ -201,7 +206,26 @@
* android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
* </group>
* </vector>
- * </pre></li>
+ * </pre>
+ * </li>
+ * <li>And here is an example of linear gradient color, which is supported in SDK 24+.
+ * See more details in {@link android.R.styleable#GradientColor} and
+ * {@link android.R.styleable#GradientColorItem}.
+ * <pre>
+ * <gradient xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:angle="90"
+ * android:startColor="?android:attr/colorPrimary"
+ * android:endColor="?android:attr/colorControlActivated"
+ * android:centerColor="#f00"
+ * android:startX="0"
+ * android:startY="0"
+ * android:endX="100"
+ * android:endY="100"
+ * android:type="linear">
+ * </gradient>
+ * </pre>
+ * </li>
+ *
*/
public class VectorDrawable extends Drawable {
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
index 2b70b6a4..cd1f8de 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -79,8 +79,12 @@
}
mInput = input;
- mNativeDocument = nativeOpen(mInput.getFd(), size);
- mPageCount = nativeGetPageCount(mNativeDocument);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ mNativeDocument = nativeOpen(mInput.getFd(), size);
+ mPageCount = nativeGetPageCount(mNativeDocument);
+ }
+
mCloseGuard.open("close");
}
@@ -102,7 +106,10 @@
public void removePage(int pageIndex) {
throwIfClosed();
throwIfPageNotInDocument(pageIndex);
- mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
+ }
}
/**
@@ -125,11 +132,16 @@
if (clip == null) {
Point size = new Point();
getPageSize(pageIndex, size);
- nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
- 0, 0, size.x, size.y);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
+ 0, 0, size.x, size.y);
+ }
} else {
- nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
- clip.left, clip.top, clip.right, clip.bottom);
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
+ clip.left, clip.top, clip.right, clip.bottom);
+ }
}
}
@@ -143,7 +155,10 @@
throwIfClosed();
throwIfOutSizeNull(outSize);
throwIfPageNotInDocument(pageIndex);
- nativeGetPageSize(mNativeDocument, pageIndex, outSize);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeGetPageSize(mNativeDocument, pageIndex, outSize);
+ }
}
/**
@@ -156,7 +171,10 @@
throwIfClosed();
throwIfOutMediaBoxNull(outMediaBox);
throwIfPageNotInDocument(pageIndex);
- return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
+ }
}
/**
@@ -169,7 +187,10 @@
throwIfClosed();
throwIfMediaBoxNull(mediaBox);
throwIfPageNotInDocument(pageIndex);
- nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
+ }
}
/**
@@ -182,7 +203,10 @@
throwIfClosed();
throwIfOutCropBoxNull(outCropBox);
throwIfPageNotInDocument(pageIndex);
- return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
+ }
}
/**
@@ -195,7 +219,10 @@
throwIfClosed();
throwIfCropBoxNull(cropBox);
throwIfPageNotInDocument(pageIndex);
- nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
+ }
}
/**
@@ -205,7 +232,10 @@
*/
public boolean shouldScaleForPrinting() {
throwIfClosed();
- return nativeScaleForPrinting(mNativeDocument);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ return nativeScaleForPrinting(mNativeDocument);
+ }
}
/**
@@ -219,7 +249,10 @@
public void write(ParcelFileDescriptor output) throws IOException {
try {
throwIfClosed();
- nativeWrite(mNativeDocument, output.getFd());
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeWrite(mNativeDocument, output.getFd());
+ }
} finally {
IoUtils.closeQuietly(output);
}
@@ -247,7 +280,9 @@
}
private void doClose() {
- nativeClose(mNativeDocument);
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeClose(mNativeDocument);
+ }
IoUtils.closeQuietly(mInput);
mInput = null;
mCloseGuard.close();
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 520ebe5..cfc1309 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -99,6 +99,12 @@
* @see #close()
*/
public final class PdfRenderer implements AutoCloseable {
+ /**
+ * Any call the native pdfium code has to be single threaded as the library does not support
+ * parallel use.
+ */
+ final static Object sPdfiumLock = new Object();
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private final Point mTempPoint = new Point();
@@ -154,8 +160,12 @@
}
mInput = input;
- mNativeDocument = nativeCreate(mInput.getFd(), size);
- mPageCount = nativeGetPageCount(mNativeDocument);
+
+ synchronized (sPdfiumLock) {
+ mNativeDocument = nativeCreate(mInput.getFd(), size);
+ mPageCount = nativeGetPageCount(mNativeDocument);
+ }
+
mCloseGuard.open("close");
}
@@ -189,7 +199,10 @@
*/
public boolean shouldScaleForPrinting() {
throwIfClosed();
- return nativeScaleForPrinting(mNativeDocument);
+
+ synchronized (sPdfiumLock) {
+ return nativeScaleForPrinting(mNativeDocument);
+ }
}
/**
@@ -224,7 +237,9 @@
if (mCurrentPage != null) {
mCurrentPage.close();
}
- nativeClose(mNativeDocument);
+ synchronized (sPdfiumLock) {
+ nativeClose(mNativeDocument);
+ }
try {
mInput.close();
} catch (IOException ioe) {
@@ -277,7 +292,9 @@
private Page(int index) {
Point size = mTempPoint;
- mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size);
+ synchronized (sPdfiumLock) {
+ mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size);
+ }
mIndex = index;
mWidth = size.x;
mHeight = size.y;
@@ -384,8 +401,10 @@
final long transformPtr = (transform != null) ? transform.native_instance : 0;
- nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
- contentTop, contentRight, contentBottom, transformPtr, renderMode);
+ synchronized (sPdfiumLock) {
+ nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
+ contentTop, contentRight, contentBottom, transformPtr, renderMode);
+ }
}
/**
@@ -412,7 +431,9 @@
}
private void doClose() {
- nativeClosePage(mNativePage);
+ synchronized (sPdfiumLock) {
+ nativeClosePage(mNativePage);
+ }
mNativePage = 0;
mCloseGuard.close();
mCurrentPage = null;
diff --git a/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml b/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml
index 20173b0..24cbfbd 100644
--- a/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml
@@ -4,7 +4,7 @@
<string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
<string name="action_use_network" msgid="6076184727448466030">"যেভাবে আছে সেভাবেই এই নেটওয়ার্ক ব্যবহার করুন"</string>
<string name="action_do_not_use_network" msgid="4577366536956516683">"এই নেটওয়ার্ক ব্যবহার করবেন না"</string>
- <string name="action_bar_label" msgid="917235635415966620">"নেটওয়ার্কে প্রবেশ করুন করুন"</string>
+ <string name="action_bar_label" msgid="917235635415966620">"নেটওয়ার্কে প্রবেশ করুন"</string>
<string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string>
<string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন"</string>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Events.java b/packages/DocumentsUI/src/com/android/documentsui/Events.java
index 14d4e2d..02a9127 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Events.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Events.java
@@ -53,7 +53,8 @@
*/
public static boolean isTouchType(int toolType) {
return toolType == MotionEvent.TOOL_TYPE_FINGER
- || toolType == MotionEvent.TOOL_TYPE_STYLUS;
+ || toolType == MotionEvent.TOOL_TYPE_STYLUS
+ || toolType == MotionEvent.TOOL_TYPE_UNKNOWN;
}
/**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index b82f8dd..ae8938d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -401,8 +401,13 @@
return true;
}
- // Open the Close drawer if it is closed and we're at the top of a root.
- if (size <= 1) {
+ final Intent intent = getIntent();
+ final boolean launchedExternally = intent != null && intent.getData() != null
+ && mState.action == State.ACTION_BROWSE;
+
+ // Open the Close drawer if it is closed and we're at the top of a root, but only when
+ // not launched by another app.
+ if (size <= 1 && !launchedExternally) {
mDrawer.setOpen(true);
// Remember so we don't just close it again if back is pressed again.
mDrawerLastFiddled = System.currentTimeMillis();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index d2e9885e..b3db037 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
import android.os.UserHandle;
import android.preference.PreferenceManager;
@@ -85,6 +86,15 @@
public @interface PermissionStatus {}
/**
+ * Clears all preferences associated with a given package.
+ *
+ * <p>Typically called when a package is removed or when user asked to clear its data.
+ */
+ static void clearPackagePreferences(Context context, String packageName) {
+ clearScopedAccessPreferences(context, packageName);
+ }
+
+ /**
* Methods below are used to keep track of denied user requests on scoped directory access so
* the dialog is not offered when user checked the 'Do not ask again' box
*
@@ -108,6 +118,23 @@
getPrefs(context).edit().putInt(key, status).apply();
}
+ private static void clearScopedAccessPreferences(Context context, String packageName) {
+ final String keySubstring = "|" + packageName + "|";
+ final SharedPreferences prefs = getPrefs(context);
+ Editor editor = null;
+ for (final String key : prefs.getAll().keySet()) {
+ if (key.contains(keySubstring)) {
+ if (editor == null) {
+ editor = prefs.edit();
+ }
+ editor.remove(key);
+ }
+ }
+ if (editor != null) {
+ editor.apply();
+ }
+ }
+
private static String getScopedAccessDenialsKey(String packageName, String uuid,
String directory) {
final int userId = UserHandle.myUserId();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java
index aef63af..fd1183f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java
@@ -23,7 +23,7 @@
import android.net.Uri;
/**
- * Clean up {@link RecentsProvider} when packages are removed.
+ * Cleans up {@link RecentsProvider} and {@link LocalPreferences} when packages are removed.
*/
public class PackageReceiver extends BroadcastReceiver {
@Override
@@ -31,15 +31,19 @@
final ContentResolver resolver = context.getContentResolver();
final String action = intent.getAction();
+ final Uri data = intent.getData();
+ final String packageName = data == null ? null : data.getSchemeSpecificPart();
+
if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
resolver.call(RecentsProvider.buildRecent(), RecentsProvider.METHOD_PURGE, null, null);
-
+ if (packageName != null) {
+ LocalPreferences.clearPackagePreferences(context, packageName);
+ }
} else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
- final Uri data = intent.getData();
- if (data != null) {
- final String packageName = data.getSchemeSpecificPart();
+ if (packageName != null) {
resolver.call(RecentsProvider.buildRecent(), RecentsProvider.METHOD_PURGE_PACKAGE,
packageName, null);
+ LocalPreferences.clearPackagePreferences(context, packageName);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index b7c0a9c..8aa7f6e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -53,10 +53,13 @@
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v13.view.DragStartHelper;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.support.v7.widget.RecyclerView.Recycler;
import android.support.v7.widget.RecyclerView.RecyclerListener;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.BidiFormatter;
@@ -243,7 +246,40 @@
mRecView.setAdapter(mAdapter);
- mLayout = new GridLayoutManager(getContext(), mColumnCount);
+ // Switch Access Accessibility API needs an {@link AccessibilityDelegate} to know the proper
+ // route when user selects an UI element. It usually guesses this if the element has an
+ // {@link OnClickListener}, but since we do not have one for itemView, we will need to
+ // manually route it to the right behavior. RecyclerView has its own AccessibilityDelegate,
+ // and routes it to its LayoutManager; so we must override the LayoutManager's accessibility
+ // methods to route clicks correctly.
+ mLayout = new GridLayoutManager(getContext(), mColumnCount) {
+ @Override
+ public void onInitializeAccessibilityNodeInfoForItem(
+ RecyclerView.Recycler recycler, RecyclerView.State state,
+ View host, AccessibilityNodeInfoCompat info) {
+ super.onInitializeAccessibilityNodeInfoForItem(recycler, state, host, info);
+ info.addAction(AccessibilityActionCompat.ACTION_CLICK);
+ }
+
+ @Override
+ public boolean performAccessibilityActionForItem(
+ RecyclerView.Recycler recycler, RecyclerView.State state, View view,
+ int action, Bundle args) {
+ // We are only handling click events; route all other to default implementation
+ if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
+ RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(view);
+ if (vh instanceof DocumentHolder) {
+ DocumentHolder dh = (DocumentHolder) vh;
+ if (dh.mEventListener != null) {
+ dh.mEventListener.onActivate(dh);
+ return true;
+ }
+ }
+ }
+ return super.performAccessibilityActionForItem(recycler, state, view, action,
+ args);
+ }
+ };
SpanSizeLookup lookup = mAdapter.createSpanSizeLookup();
if (lookup != null) {
mLayout.setSpanSizeLookup(lookup);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index 1118171..1de3bbc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -117,7 +117,9 @@
byteCopyDocument(src, dest);
// Remove the source document.
- deleteDocument(src, srcParent);
+ if(!isCanceled()) {
+ deleteDocument(src, srcParent);
+ }
}
@Override
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 78b9927..7fe0d2f 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -566,6 +566,7 @@
throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+ query = query.toLowerCase();
final File parent;
synchronized (mRootsLock) {
parent = mRoots.get(rootId).path;
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 3debf8e..d4e7963 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -60,7 +60,7 @@
<item quantity="one">找到 <xliff:g id="COUNT_0">%1$s</xliff:g> 台打印机</item>
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
- <string name="printer_info_desc" msgid="7181988788991581654">"关于此打印机的更多信息"</string>
+ <string name="printer_info_desc" msgid="7181988788991581654">"此打印机的详细信息"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"无法创建文件"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"部分打印服务已停用"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜索打印机"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 7d42211..682af8b 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -863,4 +863,7 @@
<!-- Label for Help and feedback menu item -->
<string name="help_feedback_label">Help & feedback</string>
+ <!-- Content description for drawer menu button [CHAR_LIMIT=30]-->
+ <string name="content_description_menu_button">Menu</string>
+
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 6658c14..a50b366 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -226,6 +226,7 @@
public void showMenuIcon() {
mShowingMenu = true;
getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
+ getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 284827b..aae9cf6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -29,7 +29,6 @@
import android.util.AttributeSet;
import android.util.SparseArray;
import android.widget.TextView;
-
import com.android.settingslib.R;
public class AccessPointPreference extends Preference {
@@ -44,13 +43,14 @@
private final StateListDrawable mWifiSld;
private final int mBadgePadding;
private final UserBadgeCache mBadgeCache;
-
private TextView mTitleView;
+
private boolean mForSavedNetworks = false;
private AccessPoint mAccessPoint;
private Drawable mBadge;
private int mLevel;
private CharSequence mContentDescription;
+ private int mDefaultIconResId;
static final int[] WIFI_CONNECTION_STRENGTH = {
R.string.accessibility_wifi_one_bar,
@@ -85,6 +85,24 @@
refresh();
}
+ public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache,
+ int iconResId, boolean forSavedNetworks) {
+ super(context);
+ mBadgeCache = cache;
+ mAccessPoint = accessPoint;
+ mForSavedNetworks = forSavedNetworks;
+ mAccessPoint.setTag(this);
+ mLevel = -1;
+ mDefaultIconResId = iconResId;
+
+ mWifiSld = (StateListDrawable) context.getTheme()
+ .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0);
+
+ // Distance from the end of the title at which this AP's user badge should sit.
+ mBadgePadding = context.getResources()
+ .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding);
+ }
+
public AccessPoint getAccessPoint() {
return mAccessPoint;
}
@@ -112,7 +130,7 @@
protected void updateIcon(int level, Context context) {
if (level == -1) {
- setIcon(null);
+ safeSetDefaultIcon();
} else {
if (getIcon() == null) {
// To avoid a drawing race condition, we first set the state (SECURE/NONE) and then
@@ -124,16 +142,24 @@
? STATE_SECURED
: STATE_NONE);
Drawable drawable = mWifiSld.getCurrent();
- if (!mForSavedNetworks) {
+ if (!mForSavedNetworks && drawable != null) {
setIcon(drawable);
- } else {
- setIcon(null);
+ return;
}
}
+ safeSetDefaultIcon();
}
}
}
+ private void safeSetDefaultIcon() {
+ if (mDefaultIconResId != 0) {
+ setIcon(mDefaultIconResId);
+ } else {
+ setIcon(null);
+ }
+ }
+
protected void updateBadge(Context context) {
WifiConfiguration config = mAccessPoint.getConfig();
if (config != null) {
diff --git a/packages/SystemUI/res/values-bs-rBA-land/strings.xml b/packages/SystemUI/res/values-bs-rBA-land/strings.xml
index bdc652a..56a4ad2 100644
--- a/packages/SystemUI/res/values-bs-rBA-land/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA-land/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="toast_rotation_locked" msgid="7609673011431556092">"Ekran je sada zaključan u pejzažnom prikazu."</string>
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Ekran je sada zaključan u vodoravnom prikazu."</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings_car.xml b/packages/SystemUI/res/values-it/strings_car.xml
index ae26c9e..19c4e2b 100644
--- a/packages/SystemUI/res/values-it/strings_car.xml
+++ b/packages/SystemUI/res/values-it/strings_car.xml
@@ -20,5 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Guida in modo sicuro"</string>
- <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"È necessario essere sempre pienamente coscienti delle condizioni di guida e rispettare le leggi vigenti. Le indicazioni stradali potrebbero essere imprecise, incomplete, pericolose, non adatte, vietate o implicare l\'attraversamento di confini. Anche le informazioni sulle attività commerciali potrebbero essere imprecise o incomplete. I dati non vengono forniti in tempo reale e non è possibile garantire la precisione della geolocalizzazione. Non maneggiare il dispositivo mobile e non utilizzare app non progettate per Android Auto durante la guida."</string>
+ <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"È necessario essere sempre pienamente informati sulle condizioni della strada e rispettare la legislazione vigente. Le indicazioni stradali potrebbero essere imprecise, incomplete, pericolose, inadatte, vietate o richiedere l\'attraversamento di aree amministrative. Anche le informazioni sugli esercizi commerciali potrebbero essere imprecise o incomplete. I dati forniti non sono aggiornati in tempo reale e non è possibile garantire la precisione della geolocalizzazione. Non maneggiare dispositivi mobili e app non destinate ad Android Auto durante la guida."</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
index bad739fd..4585fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
@@ -62,36 +62,36 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
Data data = mStrokeMap.get(stroke);
- return SpeedRatioEvaluator.evaluate(data.maxSpeedRatio)
- + DistanceRatioEvaluator.evaluate(data.maxDistanceRatio);
+ return 2 * SpeedRatioEvaluator.evaluate(data.maxSpeedRatio);
}
private static class Data {
- public Point previousPoint;
- public float previousSpeed;
- public float previousDistance;
- public float maxSpeedRatio;
- public float maxDistanceRatio;
+
+ static final float MILLIS_TO_NANOS = 1e6f;
+
+ Point previousPoint;
+ float previousSpeed = 0;
+ float maxSpeedRatio = 0;
public Data(Point point) {
previousPoint = point;
- previousSpeed = previousDistance = 0.0f;
- maxDistanceRatio = maxSpeedRatio = 0.0f;
}
public void addPoint(Point point) {
float distance = previousPoint.dist(point);
float duration = (float) (point.timeOffsetNano - previousPoint.timeOffsetNano + 1);
float speed = distance / duration;
- if (previousDistance != 0.0f) {
- maxDistanceRatio = Math.max(maxDistanceRatio, distance / previousDistance);
- }
+ if (duration > 20 * MILLIS_TO_NANOS || duration < 5 * MILLIS_TO_NANOS) {
+ // reject this segment and ensure we won't use data about it in the next round.
+ previousSpeed = 0;
+ previousPoint = point;
+ return;
+ }
if (previousSpeed != 0.0f) {
maxSpeedRatio = Math.max(maxSpeedRatio, speed / previousSpeed);
}
- previousDistance = distance;
previousSpeed = speed;
previousPoint = point;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java
deleted file mode 100644
index 8acb009..0000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class DistanceRatioEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value <= 1.0) evaluation++;
- if (value <= 0.5) evaluation++;
- if (value > 4.0) evaluation++;
- if (value > 7.0) evaluation++;
- if (value > 14.0) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
index 4c6cea0..e34f222 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
@@ -19,6 +19,7 @@
public class SpeedRatioEvaluator {
public static float evaluate(float value) {
float evaluation = 0.0f;
+ if (value == 0) return 0;
if (value <= 1.0) evaluation++;
if (value <= 0.5) evaluation++;
if (value > 9.0) evaluation++;
diff --git a/packages/VpnDialogs/res/values-ro/strings.xml b/packages/VpnDialogs/res/values-ro/strings.xml
index 4865e96..e2e1e44 100644
--- a/packages/VpnDialogs/res/values-ro/strings.xml
+++ b/packages/VpnDialogs/res/values-ro/strings.xml
@@ -25,5 +25,5 @@
<string name="duration" msgid="3584782459928719435">"Durată:"</string>
<string name="data_transmitted" msgid="7988167672982199061">"Trimise:"</string>
<string name="data_received" msgid="4062776929376067820">"Primite:"</string>
- <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> (de) octeți/<xliff:g id="NUMBER_1">%2$s</xliff:g> (de) pachete"</string>
+ <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> octeți/<xliff:g id="NUMBER_1">%2$s</xliff:g> pachete"</string>
</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 695ea60..b1fbcde 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -451,7 +451,7 @@
}
@Override
- public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
+ public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
@@ -459,23 +459,39 @@
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// This method does nothing for a background user.
- if (resolvedUserId != mCurrentUserId) {
- return true; // yes, recycle the event
+ if (resolvedUserId == mCurrentUserId) {
+ if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
+ mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(
+ event.getWindowId(), event.getSourceNodeId(),
+ event.getEventType(), event.getAction());
+ mSecurityPolicy.updateEventSourceLocked(event);
+ notifyAccessibilityServicesDelayedLocked(event, false);
+ notifyAccessibilityServicesDelayedLocked(event, true);
+ }
+ if (mHasInputFilter && mInputFilter != null) {
+ mMainHandler.obtainMessage(
+ MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
+ AccessibilityEvent.obtain(event)).sendToTarget();
+ }
}
- if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
- mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(),
- event.getSourceNodeId(), event.getEventType(), event.getAction());
- mSecurityPolicy.updateEventSourceLocked(event);
- notifyAccessibilityServicesDelayedLocked(event, false);
- notifyAccessibilityServicesDelayedLocked(event, true);
- }
- if (mHasInputFilter && mInputFilter != null) {
- mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
- AccessibilityEvent.obtain(event)).sendToTarget();
- }
+ }
+ if (OWN_PROCESS_ID != Binder.getCallingPid()) {
event.recycle();
}
- return (OWN_PROCESS_ID != Binder.getCallingPid());
+ }
+
+ @Override
+ public void sendAccessibilityEvents(ParceledListSlice events, int userId) {
+ List<AccessibilityEvent> a11yEvents = events.getList();
+ // Grab the lock once for the entire batch
+ synchronized (mLock) {
+ int numEventsToProcess = Math.min(a11yEvents.size(),
+ AccessibilityManager.MAX_A11Y_EVENTS_PER_SERVICE_CALL);
+ for (int i = 0; i < numEventsToProcess; i++) {
+ AccessibilityEvent event = a11yEvents.get(i);
+ sendAccessibilityEvent(event, userId);
+ }
+ }
}
@Override
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index b5b0cd8..4caeba8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -875,7 +875,7 @@
return AppOpsManager.MODE_IGNORED;
}
synchronized (this) {
- if (isOpRestricted(uid, code, resolvedPackageName)) {
+ if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -1024,7 +1024,7 @@
return AppOpsManager.MODE_ERRORED;
}
Op op = getOpLocked(ops, code, true);
- if (isOpRestricted(uid, code, packageName)) {
+ if (isOpRestrictedLocked(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
if (op.duration == -1) {
@@ -1082,7 +1082,7 @@
return AppOpsManager.MODE_ERRORED;
}
Op op = getOpLocked(ops, code, true);
- if (isOpRestricted(uid, code, resolvedPackageName)) {
+ if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
return AppOpsManager.MODE_IGNORED;
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1308,7 +1308,7 @@
return op;
}
- private boolean isOpRestricted(int uid, int code, String packageName) {
+ private boolean isOpRestrictedLocked(int uid, int code, String packageName) {
int userHandle = UserHandle.getUserId(uid);
final int restrictionSetCount = mOpUserRestrictions.size();
@@ -2210,25 +2210,33 @@
private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
int userHandle, String[] exceptionPackages) {
- ClientRestrictionState restrictionState = mOpUserRestrictions.get(token);
+ boolean notifyChange = false;
- if (restrictionState == null) {
- try {
- restrictionState = new ClientRestrictionState(token);
- } catch (RemoteException e) {
- return;
+ synchronized (AppOpsService.this) {
+ ClientRestrictionState restrictionState = mOpUserRestrictions.get(token);
+
+ if (restrictionState == null) {
+ try {
+ restrictionState = new ClientRestrictionState(token);
+ } catch (RemoteException e) {
+ return;
+ }
+ mOpUserRestrictions.put(token, restrictionState);
}
- mOpUserRestrictions.put(token, restrictionState);
+
+ if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) {
+ notifyChange = true;
+ }
+
+ if (restrictionState.isDefault()) {
+ mOpUserRestrictions.remove(token);
+ restrictionState.destroy();
+ }
}
- if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) {
+ if (notifyChange) {
notifyWatchersOfChange(code);
}
-
- if (restrictionState.isDefault()) {
- mOpUserRestrictions.remove(token);
- restrictionState.destroy();
- }
}
private void notifyWatchersOfChange(int code) {
@@ -2263,10 +2271,12 @@
@Override
public void removeUser(int userHandle) throws RemoteException {
checkSystemUid("removeUser");
- final int tokenCount = mOpUserRestrictions.size();
- for (int i = tokenCount - 1; i >= 0; i--) {
- ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
- opRestrictions.removeUser(userHandle);
+ synchronized (AppOpsService.this) {
+ final int tokenCount = mOpUserRestrictions.size();
+ for (int i = tokenCount - 1; i >= 0; i--) {
+ ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
+ opRestrictions.removeUser(userHandle);
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9e601eb..ff3f159 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1158,6 +1158,7 @@
* For example, references to the commonly used services.
*/
HashMap<String, IBinder> mAppBindArgs;
+ HashMap<String, IBinder> mIsolatedAppBindArgs;
/**
* Temporary to avoid allocations. Protected by main lock.
@@ -2935,18 +2936,24 @@
* lazily setup to make sure the services are running when they're asked for.
*/
private HashMap<String, IBinder> getCommonServicesLocked(boolean isolated) {
+ // Isolated processes won't get this optimization, so that we don't
+ // violate the rules about which services they have access to.
+ if (isolated) {
+ if (mIsolatedAppBindArgs == null) {
+ mIsolatedAppBindArgs = new HashMap<>();
+ mIsolatedAppBindArgs.put("package", ServiceManager.getService("package"));
+ }
+ return mIsolatedAppBindArgs;
+ }
+
if (mAppBindArgs == null) {
mAppBindArgs = new HashMap<>();
- // Isolated processes won't get this optimization, so that we don't
- // violate the rules about which services they have access to.
- if (!isolated) {
- // Setup the application init args
- mAppBindArgs.put("package", ServiceManager.getService("package"));
- mAppBindArgs.put("window", ServiceManager.getService("window"));
- mAppBindArgs.put(Context.ALARM_SERVICE,
- ServiceManager.getService(Context.ALARM_SERVICE));
- }
+ // Setup the application init args
+ mAppBindArgs.put("package", ServiceManager.getService("package"));
+ mAppBindArgs.put("window", ServiceManager.getService("window"));
+ mAppBindArgs.put(Context.ALARM_SERVICE,
+ ServiceManager.getService(Context.ALARM_SERVICE));
}
return mAppBindArgs;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index da615ec..f3fc676 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -133,7 +133,6 @@
import android.os.HandlerThread;
import android.os.IDeviceIdleController;
import android.os.INetworkManagementService;
-import android.os.IPowerManager;
import android.os.Message;
import android.os.MessageQueue.IdleHandler;
import android.os.PowerManager;
@@ -286,7 +285,6 @@
private static final int MSG_LIMIT_REACHED = 5;
private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
- private static final int MSG_SCREEN_ON_CHANGED = 8;
private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
@@ -294,7 +292,6 @@
private final Context mContext;
private final IActivityManager mActivityManager;
- private final IPowerManager mPowerManager;
private final INetworkStatsService mNetworkStats;
private final INetworkManagementService mNetworkManager;
private UsageStatsManagerInternal mUsageStats;
@@ -312,7 +309,6 @@
@GuardedBy("allLocks") volatile boolean mSystemReady;
- @GuardedBy("mUidRulesFirstLock") volatile boolean mScreenOn;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
@GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode;
@@ -418,9 +414,8 @@
// TODO: migrate notifications to SystemUI
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
- IPowerManager powerManager, INetworkStatsService networkStats,
- INetworkManagementService networkManagement) {
- this(context, activityManager, powerManager, networkStats, networkManagement,
+ INetworkStatsService networkStats, INetworkManagementService networkManagement) {
+ this(context, activityManager, networkStats, networkManagement,
NtpTrustedTime.getInstance(context), getSystemDir(), false);
}
@@ -429,12 +424,10 @@
}
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
- IPowerManager powerManager, INetworkStatsService networkStats,
- INetworkManagementService networkManagement, TrustedTime time, File systemDir,
- boolean suppressDefaultPolicy) {
+ INetworkStatsService networkStats, INetworkManagementService networkManagement,
+ TrustedTime time, File systemDir, boolean suppressDefaultPolicy) {
mContext = checkNotNull(context, "missing context");
mActivityManager = checkNotNull(activityManager, "missing activityManager");
- mPowerManager = checkNotNull(powerManager, "missing powerManager");
mNetworkStats = checkNotNull(networkStats, "missing networkStats");
mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
@@ -618,8 +611,6 @@
}
}
- updateScreenOn();
-
try {
mActivityManager.registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE);
@@ -628,14 +619,6 @@
// ignored; both services live in system_server
}
- // TODO: traverse existing processes to know foreground state, or have
- // activitymanager dispatch current state when new observer attached.
-
- final IntentFilter screenFilter = new IntentFilter();
- screenFilter.addAction(Intent.ACTION_SCREEN_ON);
- screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
- mContext.registerReceiver(mScreenReceiver, screenFilter);
-
// listen for changes to power save whitelist
final IntentFilter whitelistFilter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
@@ -734,15 +717,6 @@
}
};
- final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // screen-related broadcasts are protected by system, no need
- // for permissions check.
- mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
- }
- };
-
final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -2520,7 +2494,7 @@
private boolean isUidStateForegroundUL(int state) {
// only really in foreground when screen is also on
- return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
+ return state <= ActivityManager.PROCESS_STATE_TOP;
}
/**
@@ -2591,31 +2565,6 @@
}
}
- private void updateScreenOn() {
- synchronized (mUidRulesFirstLock) {
- try {
- mScreenOn = mPowerManager.isInteractive();
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
- updateRulesForScreenUL();
- }
- }
-
- /**
- * Update rules that might be changed by {@link #mScreenOn} value.
- */
- private void updateRulesForScreenUL() {
- // only update rules for anyone with foreground activities
- final int size = mUidState.size();
- for (int i = 0; i < size; i++) {
- if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
- final int uid = mUidState.keyAt(i);
- updateRestrictionRulesForUidUL(uid);
- }
- }
- }
-
static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
@@ -2997,12 +2946,8 @@
mUidRules.put(uid, newUidRules);
}
- boolean changed = false;
-
// Second step: apply bw changes based on change of state.
if (newRule != oldRule) {
- changed = true;
-
if ((newRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
// Temporarily whitelist foreground app, removing from blacklist if necessary
// (since bw_penalty_box prevails over bw_happy_box).
@@ -3082,7 +3027,6 @@
final boolean isIdle = isUidIdle(uid);
final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
- final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
@@ -3105,7 +3049,7 @@
final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
if (LOGV) {
- Log.v(TAG, "updateRulesForNonMeteredNetworksUL(" + uid + ")"
+ Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
+ ", isIdle: " + isIdle
+ ", mRestrictPower: " + mRestrictPower
+ ", mDeviceIdleMode: " + mDeviceIdleMode
@@ -3347,10 +3291,6 @@
}
return true;
}
- case MSG_SCREEN_ON_CHANGED: {
- updateScreenOn();
- return true;
- }
case MSG_UPDATE_INTERFACE_QUOTA: {
removeInterfaceQuota((String) msg.obj);
// int params need to be stitched back into a long
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 6cdc40f..5831284 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -109,6 +109,7 @@
final int installerUid;
final SessionParams params;
final long createdMillis;
+ final int defaultContainerGid;
/** Staging location where client data is written. */
final File stageDir;
@@ -199,13 +200,19 @@
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
+ // Cache package manager data without the lock held
+ final PackageInfo pkgInfo = mPm.getPackageInfo(
+ params.appPackageName, PackageManager.GET_SIGNATURES /*flags*/, userId);
+ final ApplicationInfo appInfo = mPm.getApplicationInfo(
+ params.appPackageName, 0, userId);
+
synchronized (mLock) {
if (msg.obj != null) {
mRemoteObserver = (IPackageInstallObserver2) msg.obj;
}
try {
- commitLocked();
+ commitLocked(pkgInfo, appInfo);
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
@@ -264,6 +271,9 @@
} else {
mPermissionsAccepted = false;
}
+ final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ defaultContainerGid = UserHandle.getSharedAppGid(uid);
}
public SessionInfo generateInfo() {
@@ -520,7 +530,8 @@
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
}
- private void commitLocked() throws PackageManagerException {
+ private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
+ throws PackageManagerException {
if (mDestroyed) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
}
@@ -538,7 +549,7 @@
// Verify that stage looks sane with respect to existing application.
// This currently only ensures packageName, versionCode, and certificate
// consistency.
- validateInstallLocked();
+ validateInstallLocked(pkgInfo, appInfo);
Preconditions.checkNotNull(mPackageName);
Preconditions.checkNotNull(mSignatures);
@@ -650,7 +661,8 @@
* Note that upgrade compatibility is still performed by
* {@link PackageManagerService}.
*/
- private void validateInstallLocked() throws PackageManagerException {
+ private void validateInstallLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
+ throws PackageManagerException {
mPackageName = null;
mVersionCode = -1;
mSignatures = null;
@@ -729,10 +741,8 @@
if (removeSplitList.size() > 0) {
// validate split names marked for removal
- final int flags = mSignatures == null ? PackageManager.GET_SIGNATURES : 0;
- final PackageInfo pkg = mPm.getPackageInfo(params.appPackageName, flags, userId);
for (String splitName : removeSplitList) {
- if (!ArrayUtils.contains(pkg.splitNames, splitName)) {
+ if (!ArrayUtils.contains(pkgInfo.splitNames, splitName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Split not found: " + splitName);
}
@@ -740,11 +750,11 @@
// ensure we've got appropriate package name, version code and signatures
if (mPackageName == null) {
- mPackageName = pkg.packageName;
- mVersionCode = pkg.versionCode;
+ mPackageName = pkgInfo.packageName;
+ mVersionCode = pkgInfo.versionCode;
}
if (mSignatures == null) {
- mSignatures = pkg.signatures;
+ mSignatures = pkgInfo.signatures;
}
}
@@ -757,8 +767,7 @@
} else {
// Partial installs must be consistent with existing install
- final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
- if (app == null) {
+ if (appInfo == null) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Missing existing base package for " + mPackageName);
}
@@ -766,8 +775,8 @@
final PackageLite existing;
final ApkLite existingBase;
try {
- existing = PackageParser.parsePackageLite(new File(app.getCodePath()), 0);
- existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
+ existing = PackageParser.parsePackageLite(new File(appInfo.getCodePath()), 0);
+ existingBase = PackageParser.parseApkLite(new File(appInfo.getBaseCodePath()),
PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
@@ -777,7 +786,7 @@
// Inherit base if not overridden
if (mResolvedBaseFile == null) {
- mResolvedBaseFile = new File(app.getBaseCodePath());
+ mResolvedBaseFile = new File(appInfo.getBaseCodePath());
mResolvedInheritedFiles.add(mResolvedBaseFile);
}
@@ -794,7 +803,7 @@
}
// Inherit compiled oat directory.
- final File packageInstallDir = (new File(app.getBaseCodePath())).getParentFile();
+ final File packageInstallDir = (new File(appInfo.getBaseCodePath())).getParentFile();
mInheritedFilesBase = packageInstallDir;
final File oatDir = new File(packageInstallDir, "oat");
if (oatDir.exists()) {
@@ -822,7 +831,8 @@
}
}
- private void assertApkConsistent(String tag, ApkLite apk) throws PackageManagerException {
+ private void assertApkConsistent(String tag, ApkLite apk)
+ throws PackageManagerException {
if (!mPackageName.equals(apk.packageName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
+ apk.packageName + " inconsistent with " + mPackageName);
@@ -1035,10 +1045,7 @@
"Failed to finalize container " + cid);
}
- final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
- PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
- final int gid = UserHandle.getSharedAppGid(uid);
- if (!PackageHelper.fixSdPermissions(cid, gid, null)) {
+ if (!PackageHelper.fixSdPermissions(cid, defaultContainerGid, null)) {
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
"Failed to fix permissions on container " + cid);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f326555..005c6b3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8649,7 +8649,9 @@
for (i=0; i<N; i++) {
PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
- if (cur == null) {
+ final String curPackageName = cur == null ? null : cur.info.packageName;
+ final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
+ if (cur == null || isPackageUpdate) {
mPermissionGroups.put(pg.info.name, pg);
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
@@ -8657,6 +8659,9 @@
} else {
r.append(' ');
}
+ if (isPackageUpdate) {
+ r.append("UPD:");
+ }
r.append(pg.info.name);
}
} else {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c1fc7f11..b80775b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -324,10 +324,30 @@
int CHECK_LAUNCHER_ACTIVITY = 12;
int IS_ACTIVITY_ENABLED = 13;
int PACKAGE_UPDATE_CHECK = 14;
+ int ASYNC_PRELOAD_USER_DELAY = 15;
- int COUNT = PACKAGE_UPDATE_CHECK + 1;
+ int COUNT = ASYNC_PRELOAD_USER_DELAY + 1;
}
+ private static final String[] STAT_LABELS = {
+ "getHomeActivities()",
+ "Launcher permission check",
+ "getPackageInfo()",
+ "getPackageInfo(SIG)",
+ "getApplicationInfo",
+ "cleanupDanglingBitmaps",
+ "getActivity+metadata",
+ "getInstalledPackages",
+ "checkPackageChanges",
+ "getApplicationResources",
+ "resourceNameLookup",
+ "getLauncherActivity",
+ "checkLauncherActivity",
+ "isActivityEnabled",
+ "packageUpdateCheck",
+ "asyncPreloadUserDelay"
+ };
+
final Object mStatLock = new Object();
@GuardedBy("mStatLock")
@@ -533,19 +553,26 @@
/** lifecycle event */
void handleUnlockUser(int userId) {
if (DEBUG) {
- Slog.d(TAG, "handleUnlockUser: user=" + userId);
+ Slog.d(TAG, "handleUnlockUser: user=" + userId);
}
synchronized (mLock) {
mUnlockedUsers.put(userId, true);
-
- // Preload the user's shortcuts.
- // Also see if the locale has changed.
- // Note as of nyc, the locale is per-user, so the locale shouldn't change
- // when the user is locked. However due to b/30119489 it still happens.
- getUserShortcutsLocked(userId).detectLocaleChange();
-
- checkPackageChanges(userId);
}
+
+ // Preload the user data.
+ // Note, we don't use mHandler here but instead just start a new thread.
+ // This is because mHandler (which uses com.android.internal.os.BackgroundThread) is very
+ // busy at this point and this could take hundreds of milliseconds, which would be too
+ // late since the launcher would already have started.
+ // So we just create a new thread. This code runs rarely, so we don't use a thread pool
+ // or anything.
+ final long start = injectElapsedRealtime();
+ injectRunOnNewThread(() -> {
+ synchronized (mLock) {
+ logDurationStat(Stats.ASYNC_PRELOAD_USER_DELAY, start);
+ getUserShortcutsLocked(userId);
+ }
+ });
}
/** lifecycle event */
@@ -1110,6 +1137,9 @@
userPackages = new ShortcutUser(this, userId);
}
mUsers.put(userId, userPackages);
+
+ // Also when a user's data is first accessed, scan all packages.
+ checkPackageChanges(userId);
}
return userPackages;
}
@@ -1468,6 +1498,10 @@
mHandler.post(r);
}
+ void injectRunOnNewThread(Runnable r) {
+ new Thread(r).start();
+ }
+
/**
* @throws IllegalArgumentException if {@code numShortcuts} is bigger than
* {@link #getMaxActivityShortcuts()}.
@@ -3218,23 +3252,9 @@
pw.println(" Stats:");
synchronized (mStatLock) {
- final String p = " ";
- dumpStatLS(pw, p, Stats.GET_DEFAULT_HOME, "getHomeActivities()");
- dumpStatLS(pw, p, Stats.LAUNCHER_PERMISSION_CHECK, "Launcher permission check");
-
- dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO, "getPackageInfo()");
- dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO_WITH_SIG, "getPackageInfo(SIG)");
- dumpStatLS(pw, p, Stats.GET_APPLICATION_INFO, "getApplicationInfo");
- dumpStatLS(pw, p, Stats.CLEANUP_DANGLING_BITMAPS, "cleanupDanglingBitmaps");
- dumpStatLS(pw, p, Stats.GET_ACTIVITY_WITH_METADATA, "getActivity+metadata");
- dumpStatLS(pw, p, Stats.GET_INSTALLED_PACKAGES, "getInstalledPackages");
- dumpStatLS(pw, p, Stats.CHECK_PACKAGE_CHANGES, "checkPackageChanges");
- dumpStatLS(pw, p, Stats.GET_APPLICATION_RESOURCES, "getApplicationResources");
- dumpStatLS(pw, p, Stats.RESOURCE_NAME_LOOKUP, "resourceNameLookup");
- dumpStatLS(pw, p, Stats.GET_LAUNCHER_ACTIVITY, "getLauncherActivity");
- dumpStatLS(pw, p, Stats.CHECK_LAUNCHER_ACTIVITY, "checkLauncherActivity");
- dumpStatLS(pw, p, Stats.IS_ACTIVITY_ENABLED, "isActivityEnabled");
- dumpStatLS(pw, p, Stats.PACKAGE_UPDATE_CHECK, "packageUpdateCheck");
+ for (int i = 0; i < Stats.COUNT; i++) {
+ dumpStatLS(pw, " ", i);
+ }
}
pw.println();
@@ -3277,12 +3297,12 @@
return tobj.format("%Y-%m-%d %H:%M:%S");
}
- private void dumpStatLS(PrintWriter pw, String prefix, int statId, String label) {
+ private void dumpStatLS(PrintWriter pw, String prefix, int statId) {
pw.print(prefix);
final int count = mCountStats[statId];
final long dur = mDurationStats[statId];
pw.println(String.format("%s: count=%d, total=%dms, avg=%.1fms",
- label, count, dur,
+ STAT_LABELS[statId], count, dur,
(count == 0 ? 0 : ((double) dur) / count)));
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8da3a7d..a39add8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -7756,6 +7756,9 @@
}
final WindowState w = mTopFullscreenOpaqueWindowState;
+ if (w != mFocusedWindow) {
+ return false;
+ }
// We only enable seamless rotation if the top window has requested
// it and is in the fullscreen opaque state. Seamless rotation
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f2f85bf..1f82f0c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2908,12 +2908,11 @@
}
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
- final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
- if (viewVisibility == View.VISIBLE && surfaceController != null) {
+ if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
// We already told the client to go invisible, but the message may not be
// handled yet, or it might want to draw a last frame. If we already have a
// surface, let the client use that, but don't create new surface at this point.
- surfaceController.getSurface(outSurface);
+ winAnimator.mSurfaceController.getSurface(outSurface);
} else {
if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a839373..97a829e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -809,10 +809,8 @@
traceBeginAndSlog("StartNetworkPolicyManagerService");
try {
- networkPolicy = new NetworkPolicyManagerService(
- context, mActivityManagerService,
- (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE),
- networkStats, networkManagement);
+ networkPolicy = new NetworkPolicyManagerService(context,
+ mActivityManagerService, networkStats, networkManagement);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
} catch (Throwable e) {
reportWtf("starting NetworkPolicy Service", e);
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 654ef18..6d90203 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -382,6 +382,7 @@
private final State mStoppedState = new StoppedState();
private final State mStoppingState = new StoppingState();
private final State mStartedState = new StartedState();
+ private final State mRunningState = new RunningState();
private final String mTag;
private final Context mContext;
@@ -476,6 +477,7 @@
// Super simple StateMachine.
addState(mStoppedState);
addState(mStartedState);
+ addState(mRunningState, mStartedState);
addState(mStoppingState);
setInitialState(mStoppedState);
@@ -570,7 +572,7 @@
pw.decreaseIndent();
pw.println();
- pw.println("StateMachine dump:");
+ pw.println(mTag + " StateMachine dump:");
pw.increaseIndent();
mLocalLog.readOnlyLocalLog().dump(fd, pw, args);
pw.decreaseIndent();
@@ -768,6 +770,11 @@
// - IPv6 addresses
// - IPv6 routes
// - IPv6 DNS servers
+ //
+ // N.B.: this is fundamentally race-prone and should be fixed by
+ // changing NetlinkTracker from a hybrid edge/level model to an
+ // edge-only model, or by giving IpManager its own netlink socket(s)
+ // so as to track all required information directly.
LinkProperties netlinkLinkProperties = mNetlinkTracker.getLinkProperties();
newLp.setLinkAddresses(netlinkLinkProperties.getLinkAddresses());
for (RouteInfo route : netlinkLinkProperties.getRoutes()) {
@@ -939,16 +946,30 @@
return true;
}
+ private void stopAllIP() {
+ // We don't need to worry about routes, just addresses, because:
+ // - disableIpv6() will clear autoconf IPv6 routes as well, and
+ // - we don't get IPv4 routes from netlink
+ // so we neither react to nor need to wait for changes in either.
+
+ try {
+ mNwService.disableIpv6(mInterfaceName);
+ } catch (Exception e) {
+ Log.e(mTag, "Failed to disable IPv6" + e);
+ }
+
+ try {
+ mNwService.clearInterfaceAddresses(mInterfaceName);
+ } catch (Exception e) {
+ Log.e(mTag, "Failed to clear addresses " + e);
+ }
+ }
+
class StoppedState extends State {
@Override
public void enter() {
- try {
- mNwService.disableIpv6(mInterfaceName);
- mNwService.clearInterfaceAddresses(mInterfaceName);
- } catch (Exception e) {
- Log.e(mTag, "Failed to clear addresses or disable IPv6" + e);
- }
+ stopAllIP();
resetLinkProperties();
if (mStartTimeMillis > 0) {
@@ -1023,12 +1044,71 @@
}
class StartedState extends State {
- private boolean mDhcpActionInFlight;
-
@Override
public void enter() {
mStartTimeMillis = SystemClock.elapsedRealtime();
+ if (mConfiguration.mProvisioningTimeoutMs > 0) {
+ final long alarmTime = SystemClock.elapsedRealtime() +
+ mConfiguration.mProvisioningTimeoutMs;
+ mProvisioningTimeoutAlarm.schedule(alarmTime);
+ }
+
+ if (readyToProceed()) {
+ transitionTo(mRunningState);
+ } else {
+ // Clear all IPv4 and IPv6 before proceeding to RunningState.
+ // Clean up any leftover state from an abnormal exit from
+ // tethering or during an IpManager restart.
+ stopAllIP();
+ }
+ }
+
+ @Override
+ public void exit() {
+ mProvisioningTimeoutAlarm.cancel();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_STOP:
+ transitionTo(mStoppingState);
+ break;
+
+ case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+ handleLinkPropertiesUpdate(NO_CALLBACKS);
+ if (readyToProceed()) {
+ transitionTo(mRunningState);
+ }
+ break;
+
+ case EVENT_PROVISIONING_TIMEOUT:
+ handleProvisioningFailure();
+ break;
+
+ default:
+ // It's safe to process messages out of order because the
+ // only message that can both
+ // a) be received at this time and
+ // b) affect provisioning state
+ // is EVENT_NETLINK_LINKPROPERTIES_CHANGED (handled above).
+ deferMessage(msg);
+ }
+ return HANDLED;
+ }
+
+ boolean readyToProceed() {
+ return (!mLinkProperties.hasIPv4Address() &&
+ !mLinkProperties.hasGlobalIPv6Address());
+ }
+ }
+
+ class RunningState extends State {
+ private boolean mDhcpActionInFlight;
+
+ @Override
+ public void enter() {
mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
mCallback, mMulticastFiltering);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
@@ -1037,12 +1117,6 @@
mCallback.setFallbackMulticastFilter(mMulticastFiltering);
}
- if (mConfiguration.mProvisioningTimeoutMs > 0) {
- final long alarmTime = SystemClock.elapsedRealtime() +
- mConfiguration.mProvisioningTimeoutMs;
- mProvisioningTimeoutAlarm.schedule(alarmTime);
- }
-
if (mConfiguration.mEnableIPv6) {
// TODO: Consider transitionTo(mStoppingState) if this fails.
startIPv6();
@@ -1070,7 +1144,6 @@
@Override
public void exit() {
- mProvisioningTimeoutAlarm.cancel();
stopDhcpAction();
if (mIpReachabilityMonitor != null) {
@@ -1167,10 +1240,6 @@
break;
}
- case EVENT_PROVISIONING_TIMEOUT:
- handleProvisioningFailure();
- break;
-
case EVENT_DHCPACTION_TIMEOUT:
stopDhcpAction();
break;
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index 026a2ad..6e3e6c6 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -131,18 +131,10 @@
public void testSendAccessibilityEvent_AccessibilityEnabled() throws Exception {
AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
- when(mMockService.sendAccessibilityEvent(eq(sentEvent), anyInt()))
- .thenReturn(true /* should recycle event object */)
- .thenReturn(false /* should not recycle event object */);
-
AccessibilityManager manager = createManager(true);
manager.sendAccessibilityEvent(sentEvent);
assertSame("The event should be recycled.", sentEvent, AccessibilityEvent.obtain());
-
- manager.sendAccessibilityEvent(sentEvent);
-
- assertNotSame("The event should not be recycled.", sentEvent, AccessibilityEvent.obtain());
}
@MediumTest
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 979f160..541be3d 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -69,7 +69,6 @@
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.IPowerManager;
import android.os.MessageQueue.IdleHandler;
import android.os.UserHandle;
import android.test.AndroidTestCase;
@@ -115,7 +114,6 @@
private File mPolicyDir;
private IActivityManager mActivityManager;
- private IPowerManager mPowerManager;
private INetworkStatsService mStatsService;
private INetworkManagementService mNetworkManager;
private INetworkPolicyListener mPolicyListener;
@@ -187,7 +185,6 @@
}
mActivityManager = createMock(IActivityManager.class);
- mPowerManager = createMock(IPowerManager.class);
mStatsService = createMock(INetworkStatsService.class);
mNetworkManager = createMock(INetworkManagementService.class);
mPolicyListener = createMock(INetworkPolicyListener.class);
@@ -195,7 +192,7 @@
mConnManager = createMock(IConnectivityManager.class);
mNotifManager = createMock(INotificationManager.class);
- mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mPowerManager,
+ mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
mStatsService, mNetworkManager, mTime, mPolicyDir, true);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
@@ -217,8 +214,6 @@
mNetworkManager.registerObserver(capture(networkObserver));
expectLastCall().atLeastOnce();
- // expect to answer screen status during systemReady()
- expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
expectCurrentTime();
@@ -240,7 +235,6 @@
mPolicyDir = null;
mActivityManager = null;
- mPowerManager = null;
mStatsService = null;
mPolicyListener = null;
mTime = null;
@@ -313,48 +307,6 @@
}
@Suppress
- public void testScreenChangesRules() throws Exception {
- Future<Void> future;
-
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // push strict policy for foreground uid, verify ALLOW rule
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // now turn screen off and verify REJECT rule
- expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
- future.get();
- verifyAndReset();
-
- // and turn screen back on, verify ALLOW rule restored
- expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
- future.get();
- verifyAndReset();
- }
-
- @Suppress
public void testPolicyNone() throws Exception {
Future<Void> future;
@@ -1049,14 +1001,14 @@
}
private void replay() {
- EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManager, mTime, mConnManager, mNotifManager);
+ EasyMock.replay(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+ mConnManager, mNotifManager);
}
private void verifyAndReset() {
- EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManager, mTime, mConnManager, mNotifManager);
- EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManager, mTime, mConnManager, mNotifManager);
+ EasyMock.verify(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+ mConnManager, mNotifManager);
+ EasyMock.reset(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+ mConnManager, mNotifManager);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 1c7a138..e96e97b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -390,6 +390,11 @@
}
@Override
+ void injectRunOnNewThread(Runnable r) {
+ runOnHandler(r);
+ }
+
+ @Override
void injectEnforceCallingPermission(String permission, String message) {
if (!mCallerPermissions.contains(permission)) {
throw new SecurityException("Missing permission: " + permission);
@@ -921,6 +926,12 @@
});
}
+ protected void setPackageLastUpdateTime(String packageName, long value) {
+ updatePackageInfo(packageName, pi -> {
+ pi.lastUpdateTime = value;
+ });
+ }
+
protected void uninstallPackage(int userId, String packageName) {
if (ENABLE_DUMP) {
Log.v(TAG, "Unnstall package " + packageName + " / " + userId);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 253334e..ed4e391 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -3945,11 +3945,11 @@
mInjectedPackages.remove(CALLING_PACKAGE_1);
mInjectedPackages.remove(CALLING_PACKAGE_3);
- mService.handleUnlockUser(USER_0);
+ mService.checkPackageChanges(USER_0);
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
- assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
+ assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); // ---------------
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
@@ -3961,7 +3961,7 @@
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
- mService.handleUnlockUser(USER_10);
+ mService.checkPackageChanges(USER_10);
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4154,7 +4154,7 @@
updatePackageVersion(CALLING_PACKAGE_1, 1);
// Then send the broadcast, to only user-0.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
waitOnMainThread();
@@ -4186,10 +4186,13 @@
mInjectedCurrentTimeMillis = START_TIME + 200;
mRunningUsers.put(USER_10, true);
+ mUnlockedUsers.put(USER_10, true);
reset(c0);
reset(c10);
+ setPackageLastUpdateTime(CALLING_PACKAGE_1, mInjectedCurrentTimeMillis);
mService.handleUnlockUser(USER_10);
+ mService.checkPackageChanges(USER_10);
waitOnMainThread();
@@ -4221,7 +4224,7 @@
// Then send the broadcast, to only user-0.
mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
- mService.handleUnlockUser(USER_10);
+ mService.checkPackageChanges(USER_10);
waitOnMainThread();
@@ -4243,9 +4246,9 @@
updatePackageVersion(CALLING_PACKAGE_3, 100);
// Then send the broadcast, to only user-0.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
- mService.handleUnlockUser(USER_10);
+ mService.checkPackageChanges(USER_10);
waitOnMainThread();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 43d2a1f..a04034e3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -535,6 +535,18 @@
+ " user=" + userHandle);
}
+ ComponentName getCurAssistant(int userHandle) {
+ String curAssistant = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ASSISTANT, userHandle);
+ if (TextUtils.isEmpty(curAssistant)) {
+ return null;
+ }
+ if (DEBUG) Slog.d(TAG, "getCurAssistant curAssistant=" + curAssistant
+ + " user=" + userHandle);
+ return ComponentName.unflattenFromString(curAssistant);
+ }
+
void resetCurAssistant(int userHandle) {
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.ASSISTANT, null, userHandle);
@@ -1178,6 +1190,7 @@
synchronized (VoiceInteractionManagerServiceStub.this) {
ComponentName curInteractor = getCurInteractor(userHandle);
ComponentName curRecognizer = getCurRecognizer(userHandle);
+ ComponentName curAssistant = getCurAssistant(userHandle);
if (curRecognizer == null) {
// Could a new recognizer appear when we don't have one pre-installed?
if (anyPackagesAppearing()) {
@@ -1196,6 +1209,7 @@
// the default config.
setCurInteractor(null, userHandle);
setCurRecognizer(null, userHandle);
+ resetCurAssistant(userHandle);
initForUser(userHandle);
return;
}
@@ -1212,6 +1226,20 @@
return;
}
+ if (curAssistant != null) {
+ int change = isPackageDisappearing(curAssistant.getPackageName());
+ if (change == PACKAGE_PERMANENT_CHANGE) {
+ // If the currently set assistant is being removed, then we should
+ // reset back to the default state (which is probably that we prefer
+ // to have the default full voice interactor enabled).
+ setCurInteractor(null, userHandle);
+ setCurRecognizer(null, userHandle);
+ resetCurAssistant(userHandle);
+ initForUser(userHandle);
+ return;
+ }
+ }
+
// There is no interactor, so just deal with a simple recognizer.
int change = isPackageDisappearing(curRecognizer.getPackageName());
if (change == PACKAGE_PERMANENT_CHANGE
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4da5ff2..a093d54 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -461,6 +461,32 @@
*/
public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
+ /**
+ * Connection event used to inform {@link InCallService}s when a call has been put on hold by
+ * the remote party.
+ * <p>
+ * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the
+ * call is being held locally on the device. When a capable {@link ConnectionService} receives
+ * signalling to indicate that the remote party has put the call on hold, it can send this
+ * connection event.
+ * @hide
+ */
+ public static final String EVENT_CALL_REMOTELY_HELD =
+ "android.telecom.event.CALL_REMOTELY_HELD";
+
+ /**
+ * Connection event used to inform {@link InCallService}s when a call which was remotely held
+ * (see {@link #EVENT_CALL_REMOTELY_HELD}) has been un-held by the remote party.
+ * <p>
+ * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the
+ * call is being held locally on the device. When a capable {@link ConnectionService} receives
+ * signalling to indicate that the remote party has taken the call off hold, it can send this
+ * connection event.
+ * @hide
+ */
+ public static final String EVENT_CALL_REMOTELY_UNHELD =
+ "android.telecom.event.CALL_REMOTELY_UNHELD";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index 2956d87..7ec46a3e 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -256,8 +256,8 @@
def check_emoji_coverage(all_emoji, equivalent_emoji):
- emoji_font = get_emoji_font()
- check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji)
+ emoji_font = get_emoji_font()
+ check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji)
def get_emoji_font():
@@ -274,15 +274,12 @@
assert sequence in coverage, (
'%s is not supported in the emoji font.' % printable(sequence))
- # disable temporarily - we cover more than this
- """
for sequence in coverage:
if sequence in {0x0000, 0x000D, 0x0020}:
# The font needs to support a few extra characters, which is OK
continue
assert sequence in all_emoji, (
'Emoji font should not support %s.' % printable(sequence))
- """
for first, second in sorted(equivalent_emoji.items()):
assert coverage[first] == coverage[second], (
@@ -290,8 +287,6 @@
printable(first),
printable(second)))
- # disable temporarily - some equivalent sequences we don't even know about
- """
for glyph in set(coverage.values()):
maps_to_glyph = [seq for seq in coverage if coverage[seq] == glyph]
if len(maps_to_glyph) > 1:
@@ -307,7 +302,7 @@
'The sequences %s should not result in the same glyph %s' % (
printable(equivalent_seqs),
glyph))
- """
+
def check_emoji_defaults(default_emoji):
missing_text_chars = _emoji_properties['Emoji'] - default_emoji
@@ -334,15 +329,9 @@
# Noto does not have monochrome glyphs for Unicode 7.0 wingdings and
# webdings yet.
missing_text_chars -= _chars_by_age['7.0']
- # TODO: Remove these after b/26113320 is fixed
- missing_text_chars -= {
- 0x263A, # WHITE SMILING FACE
- 0x270C, # VICTORY HAND
- 0x2744, # SNOWFLAKE
- 0x2764, # HEAVY BLACK HEART
- }
assert missing_text_chars == set(), (
- 'Text style version of some emoji characters are missing: ' + repr(missing_text_chars))
+ 'Text style version of some emoji characters are missing: ' +
+ repr(missing_text_chars))
# Setting reverse to true returns a dictionary that maps the values to sets of
@@ -362,7 +351,7 @@
if not line:
continue
- chars, prop = line.split(';')
+ chars, prop = line.split(';')[:2]
chars = chars.strip()
prop = prop.strip()
@@ -423,26 +412,6 @@
_emoji_zwj_sequences = parse_unicode_datafile(
path.join(ucd_path, 'emoji-zwj-sequences.txt'))
- # filter modern pentathlon, as it seems likely to be removed from final spec
- # also filter rifle
- def is_excluded(n):
- return n in [0x1f93b, 0x1f946]
-
- def contains_excluded(t):
- if type(t) == int:
- return is_excluded(t)
- return any(is_excluded(cp) for cp in t)
-
- # filter modern pentathlon, as it seems likely to be removed from final spec
- _emoji_properties['Emoji'] = set(
- t for t in _emoji_properties['Emoji'] if not contains_excluded(t))
- _emoji_sequences = dict(
- (t, v) for (t, v) in _emoji_sequences.items() if not contains_excluded(t))
-
- # add in UN flag
- UN_seq = flag_sequence('UN')
- _emoji_sequences[UN_seq] = 'Emoji_Flag_Sequence'
-
def flag_sequence(territory_code):
return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
@@ -454,7 +423,8 @@
flag_sequence('GF'), flag_sequence('GP'), flag_sequence('GS'),
flag_sequence('MF'), flag_sequence('MQ'), flag_sequence('NC'),
flag_sequence('PM'), flag_sequence('RE'), flag_sequence('TF'),
- flag_sequence('WF'), flag_sequence('XK'), flag_sequence('YT'),
+ flag_sequence('UN'), flag_sequence('WF'), flag_sequence('XK'),
+ flag_sequence('YT'),
})
EQUIVALENT_FLAGS = {
@@ -467,6 +437,22 @@
COMBINING_KEYCAP = 0x20E3
+# Characters that Android defaults to emoji style, different from the recommendations in UTR #51
+ANDROID_DEFAULT_EMOJI = frozenset({
+ 0x2600, # BLACK SUN WITH RAYS
+ 0x2601, # CLOUD
+ 0x260E, # BLACK TELEPHONE
+ 0x261D, # WHITE UP POINTING INDEX
+ 0x263A, # WHITE SMILING FACE
+ 0x2660, # BLACK SPADE SUIT
+ 0x2663, # BLACK CLUB SUIT
+ 0x2665, # BLACK HEART SUIT
+ 0x2666, # BLACK DIAMOND SUIT
+ 0x270C, # VICTORY HAND
+ 0x2744, # SNOWFLAKE
+ 0x2764, # HEAVY BLACK HEART
+})
+
LEGACY_ANDROID_EMOJI = {
0xFE4E5: flag_sequence('JP'),
0xFE4E6: flag_sequence('US'),
@@ -502,7 +488,17 @@
def is_fitzpatrick_modifier(cp):
- return 0x1f3fb <= cp <= 0x1f3ff
+ return 0x1F3FB <= cp <= 0x1F3FF
+
+
+def reverse_emoji(seq):
+ rev = list(reversed(seq))
+ # if there are fitzpatrick modifiers in the sequence, keep them after
+ # the emoji they modify
+ for i in xrange(1, len(rev)):
+ if is_fitzpatrick_modifier(rev[i-1]):
+ rev[i], rev[i-1] = rev[i-1], rev[i]
+ return tuple(rev)
def compute_expected_emoji():
@@ -511,26 +507,52 @@
all_sequences = set()
all_sequences.update(_emoji_variation_sequences)
+ # add zwj sequences not in the current emoji-zwj-sequences.txt
+ adjusted_emoji_zwj_sequences = dict(_emoji_zwj_sequences)
+ adjusted_emoji_zwj_sequences.update(_emoji_zwj_sequences)
+ # single parent families
+ additional_emoji_zwj = (
+ (0x1F468, 0x200D, 0x1F466),
+ (0x1F468, 0x200D, 0x1F467),
+ (0x1F468, 0x200D, 0x1F466, 0x200D, 0x1F466),
+ (0x1F468, 0x200D, 0x1F467, 0x200D, 0x1F466),
+ (0x1F468, 0x200D, 0x1F467, 0x200D, 0x1F467),
+ (0x1F469, 0x200D, 0x1F466),
+ (0x1F469, 0x200D, 0x1F467),
+ (0x1F469, 0x200D, 0x1F466, 0x200D, 0x1F466),
+ (0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F466),
+ (0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F467),
+ )
+ # sequences formed from man and woman and optional fitzpatrick modifier
+ modified_extensions = (
+ 0x2696,
+ 0x2708,
+ 0x1F3A8,
+ 0x1F680,
+ 0x1F692,
+ )
+ for seq in additional_emoji_zwj:
+ adjusted_emoji_zwj_sequences[seq] = 'Emoji_ZWJ_Sequence'
+ for ext in modified_extensions:
+ for base in (0x1F468, 0x1F469):
+ seq = (base, 0x200D, ext)
+ adjusted_emoji_zwj_sequences[seq] = 'Emoji_ZWJ_Sequence'
+ for modifier in range(0x1F3FB, 0x1F400):
+ seq = (base, modifier, 0x200D, ext)
+ adjusted_emoji_zwj_sequences[seq] = 'Emoji_ZWJ_Sequence'
+
for sequence in _emoji_sequences.keys():
sequence = tuple(ch for ch in sequence if ch != EMOJI_VS)
all_sequences.add(sequence)
sequence_pieces.update(sequence)
- for sequence in _emoji_zwj_sequences.keys():
+ for sequence in adjusted_emoji_zwj_sequences.keys():
sequence = tuple(ch for ch in sequence if ch != EMOJI_VS)
all_sequences.add(sequence)
sequence_pieces.update(sequence)
# Add reverse of all emoji ZWJ sequences, which are added to the fonts
# as a workaround to get the sequences work in RTL text.
- reversed_seq = list(reversed(sequence))
- # if there are fitzpatrick modifiers in the sequence, keep them after
- # the emoji they modify
- for i in xrange(1, len(reversed_seq)):
- if is_fitzpatrick_modifier(reversed_seq[i - 1]):
- tmp = reversed_seq[i]
- reversed_seq[i] = reversed_seq[i-1]
- reversed_seq[i-1] = tmp
- reversed_seq = tuple(reversed_seq)
+ reversed_seq = reverse_emoji(sequence)
all_sequences.add(reversed_seq)
equivalent_emoji[reversed_seq] = sequence
@@ -549,6 +571,7 @@
set(LEGACY_ANDROID_EMOJI.keys()))
default_emoji = (
_emoji_properties['Emoji_Presentation'] |
+ ANDROID_DEFAULT_EMOJI |
all_sequences |
set(LEGACY_ANDROID_EMOJI.keys()))
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 9d0c20c..d3d5ea0 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -817,6 +817,7 @@
*/
public static final int NETWORK_SELECTION_ENABLE = 0;
/**
+ * @deprecated it is not used any more.
* This network is disabled because higher layer (>2) network is bad
*/
public static final int DISABLED_BAD_LINK = 1;
@@ -862,7 +863,7 @@
*/
private static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = {
"NETWORK_SELECTION_ENABLE",
- "NETWORK_SELECTION_DISABLED_BAD_LINK",
+ "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated
"NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ",
"NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE",
"NETWORK_SELECTION_DISABLED_DHCP_FAILURE",