Merge "PIP: Fix regressions caused by previous commit a0d4d25" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 7d1ee38..f4efc92 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20328,8 +20328,8 @@
public class MediaActionSound {
ctor public MediaActionSound();
- method public synchronized void load(int);
- method public synchronized void play(int);
+ method public void load(int);
+ method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -36621,7 +36621,6 @@
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
method public boolean isInCall();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -37310,7 +37309,8 @@
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getGroupIdLevel1(int);
- method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
method public java.lang.String getLine1Number(int);
@@ -37379,6 +37379,13 @@
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+ field public static final int APPTYPE_CSIM = 4; // 0x4
+ field public static final int APPTYPE_ISIM = 5; // 0x5
+ field public static final int APPTYPE_RUIM = 3; // 0x3
+ field public static final int APPTYPE_SIM = 1; // 0x1
+ field public static final int APPTYPE_USIM = 2; // 0x2
+ field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+ field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -44094,8 +44101,6 @@
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -46266,7 +46271,7 @@
method public long getMinDate();
method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
method public deprecated int getSelectedWeekBackgroundColor();
- method public boolean getShowWeekNumber();
+ method public deprecated boolean getShowWeekNumber();
method public deprecated int getShownWeekCount();
method public deprecated int getUnfocusedMonthDateColor();
method public int getWeekDayTextAppearance();
@@ -46283,7 +46288,7 @@
method public deprecated void setSelectedDateVerticalBar(int);
method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
method public deprecated void setSelectedWeekBackgroundColor(int);
- method public void setShowWeekNumber(boolean);
+ method public deprecated void setShowWeekNumber(boolean);
method public deprecated void setShownWeekCount(int);
method public deprecated void setUnfocusedMonthDateColor(int);
method public void setWeekDayTextAppearance(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index ff5747a..521b853 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21807,8 +21807,8 @@
public class MediaActionSound {
ctor public MediaActionSound();
- method public synchronized void load(int);
- method public synchronized void play(int);
+ method public void load(int);
+ method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -39290,7 +39290,6 @@
method public boolean isRinging();
method public boolean isTtySupported();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -40005,7 +40004,8 @@
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getGroupIdLevel1(int);
- method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
method public java.lang.String getLine1Number(int);
@@ -40095,6 +40095,13 @@
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
+ field public static final int APPTYPE_CSIM = 4; // 0x4
+ field public static final int APPTYPE_ISIM = 5; // 0x5
+ field public static final int APPTYPE_RUIM = 3; // 0x3
+ field public static final int APPTYPE_SIM = 1; // 0x1
+ field public static final int APPTYPE_USIM = 2; // 0x2
+ field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+ field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -46837,8 +46844,6 @@
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -49363,7 +49368,7 @@
method public long getMinDate();
method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
method public deprecated int getSelectedWeekBackgroundColor();
- method public boolean getShowWeekNumber();
+ method public deprecated boolean getShowWeekNumber();
method public deprecated int getShownWeekCount();
method public deprecated int getUnfocusedMonthDateColor();
method public int getWeekDayTextAppearance();
@@ -49380,7 +49385,7 @@
method public deprecated void setSelectedDateVerticalBar(int);
method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
method public deprecated void setSelectedWeekBackgroundColor(int);
- method public void setShowWeekNumber(boolean);
+ method public deprecated void setShowWeekNumber(boolean);
method public deprecated void setShownWeekCount(int);
method public deprecated void setUnfocusedMonthDateColor(int);
method public void setWeekDayTextAppearance(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 5163e95..7ae0f97 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -20393,8 +20393,8 @@
public class MediaActionSound {
ctor public MediaActionSound();
- method public synchronized void load(int);
- method public synchronized void play(int);
+ method public void load(int);
+ method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -36693,7 +36693,6 @@
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
method public boolean isInCall();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -37382,7 +37381,8 @@
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getGroupIdLevel1(int);
- method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
method public java.lang.String getLine1Number(int);
@@ -37451,6 +37451,13 @@
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+ field public static final int APPTYPE_CSIM = 4; // 0x4
+ field public static final int APPTYPE_ISIM = 5; // 0x5
+ field public static final int APPTYPE_RUIM = 3; // 0x3
+ field public static final int APPTYPE_SIM = 1; // 0x1
+ field public static final int APPTYPE_USIM = 2; // 0x2
+ field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+ field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -44168,8 +44175,6 @@
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -46340,7 +46345,7 @@
method public long getMinDate();
method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
method public deprecated int getSelectedWeekBackgroundColor();
- method public boolean getShowWeekNumber();
+ method public deprecated boolean getShowWeekNumber();
method public deprecated int getShownWeekCount();
method public deprecated int getUnfocusedMonthDateColor();
method public int getWeekDayTextAppearance();
@@ -46357,7 +46362,7 @@
method public deprecated void setSelectedDateVerticalBar(int);
method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
method public deprecated void setSelectedWeekBackgroundColor(int);
- method public void setShowWeekNumber(boolean);
+ method public deprecated void setShowWeekNumber(boolean);
method public deprecated void setShownWeekCount(int);
method public deprecated void setUnfocusedMonthDateColor(int);
method public void setWeekDayTextAppearance(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 221b2d3..456be02 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -44,6 +44,7 @@
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
@@ -96,6 +97,7 @@
private static final int STACK_BOUNDS_INSET = 10;
private IActivityManager mAm;
+ private IPackageManager mPm;
private int mStartFlags = 0;
private boolean mWaitOption = false;
@@ -224,7 +226,8 @@
" --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
"\n" +
"am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +
- " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" +
+ " is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there \n" +
+ " is only one instrumentation. Options are:\n" +
" -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" +
" [-e perf true] to generate raw output for performance measurements.\n" +
" -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" +
@@ -373,6 +376,12 @@
throw new AndroidException("Can't connect to activity manager; is the system running?");
}
+ mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ if (mPm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't connect to package manager; is the system running?");
+ }
+
String op = nextArgRequired();
if (op.equals("start")) {
@@ -570,13 +579,7 @@
if (intent.getComponent() != null) {
packageName = intent.getComponent().getPackageName();
} else {
- IPackageManager pm = IPackageManager.Stub.asInterface(
- ServiceManager.getService("package"));
- if (pm == null) {
- System.err.println("Error: Package manager not running; aborting");
- return;
- }
- List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
+ List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
mUserId).getList();
if (activities == null || activities.size() <= 0) {
System.err.println("Error: Intent does not match any activities: "
@@ -813,8 +816,44 @@
}
String cnArg = nextArgRequired();
- ComponentName cn = ComponentName.unflattenFromString(cnArg);
- if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+
+ ComponentName cn;
+ if (cnArg.contains("/")) {
+ cn = ComponentName.unflattenFromString(cnArg);
+ if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+ } else {
+ List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
+
+ final int numInfos = infos == null ? 0: infos.size();
+ List<ComponentName> cns = new ArrayList<>();
+ for (int i = 0; i < numInfos; i++) {
+ InstrumentationInfo info = infos.get(i);
+
+ ComponentName c = new ComponentName(info.packageName, info.name);
+ if (cnArg.equals(info.packageName)) {
+ cns.add(c);
+ }
+ }
+
+ if (cns.size() == 0) {
+ throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
+ } else if (cns.size() == 1) {
+ cn = cns.get(0);
+ } else {
+ StringBuilder cnsStr = new StringBuilder();
+ final int numCns = cns.size();
+ for (int i = 0; i < numCns; i++) {
+ cnsStr.append(cns.get(i).flattenToString());
+ cnsStr.append(", ");
+ }
+
+ // Remove last ", "
+ cnsStr.setLength(cnsStr.length() - 2);
+
+ throw new IllegalArgumentException("Found multiple instrumentations: "
+ + cnsStr.toString());
+ }
+ }
InstrumentationWatcher watcher = null;
UiAutomationConnection connection = null;
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 3a51aff..1e2cc26 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -146,6 +146,10 @@
op.removed.add(r);
}
}
+ bse.mEnterAnim = op.enterAnim;
+ bse.mExitAnim = op.exitAnim;
+ bse.mPopEnterAnim = op.popEnterAnim;
+ bse.mPopExitAnim = op.popExitAnim;
bse.addOp(op);
num++;
}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 801c951..8e515e2 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -427,23 +427,31 @@
}
/**
- * Tells the application agent that the backup data size exceeded current transport quota.
- * Later calls to {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
- * and {@link #onFullBackup(FullBackupDataOutput)} could use this information
- * to reduce backup size under the limit.
- * However, the quota can change, so do not assume that the value passed in here is absolute,
- * similarly all subsequent backups should not be restricted to this size.
- * This callback will be invoked before data has been put onto the wire in a preflight check,
- * so it is relatively inexpensive to hit your quota.
- * Apps that hit quota repeatedly without dealing with it can be subject to having their backup
- * schedule reduced.
- * The {@code quotaBytes} is a loose guideline b/c of metadata added by the backupmanager
- * so apps should be more aggressive in trimming their backup set.
+ * Notification that the application's current backup operation causes it to exceed
+ * the maximum size permitted by the transport. The ongoing backup operation is
+ * halted and rolled back: any data that had been stored by a previous backup operation
+ * is still intact. Typically the quota-exceeded state will be detected before any data
+ * is actually transmitted over the network.
*
- * @param backupDataBytes Expected or already processed amount of data.
- * Could be less than total backup size if backup process was interrupted
- * before finish of processing all backup data.
- * @param quotaBytes Current amount of backup data that is allowed for the app.
+ * <p>The {@code quotaBytes} value is the total data size currently permitted for this
+ * application. If desired, the application can use this as a hint for determining
+ * how much data to store. For example, a messaging application might choose to
+ * store only the newest messages, dropping enough older content to stay under
+ * the quota.
+ *
+ * <p class="note">Note that the maximum quota for the application can change over
+ * time. In particular, in the future the quota may grow. Applications that adapt
+ * to the quota when deciding what data to store should be aware of this and implement
+ * their data storage mechanisms in a way that can take advantage of additional
+ * quota.
+ *
+ * @param backupDataBytes The amount of data measured while initializing the backup
+ * operation, if the total exceeds the app's alloted quota. If initial measurement
+ * suggested that the data would fit but then too much data was actually submitted
+ * as part of the operation, then this value is the amount of data that had been
+ * streamed into the transport at the time the quota was reached.
+ * @param quotaBytes The maximum data size that the transport currently permits
+ * this application to store as a backup.
*/
public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
}
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 1af4953..2d9f4a7 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -17,8 +17,7 @@
package android.appwidget;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.List;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,7 +34,9 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.util.DisplayMetrics;
+import android.util.SparseArray;
import android.util.TypedValue;
import android.widget.RemoteViews;
import android.widget.RemoteViews.OnClickHandler;
@@ -62,7 +63,7 @@
private final Handler mHandler;
private final int mHostId;
private final Callbacks mCallbacks;
- private final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
+ private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
private OnClickHandler mOnClickHandler;
static class Callbacks extends IAppWidgetHost.Stub {
@@ -164,7 +165,6 @@
bindService();
}
-
private static void bindService() {
synchronized (sServiceLock) {
if (sService == null) {
@@ -179,17 +179,25 @@
* becomes visible, i.e. from onStart() in your Activity.
*/
public void startListening() {
- int[] updatedIds;
- ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
+ final int[] idsToUpdate;
+ synchronized (mViews) {
+ int N = mViews.size();
+ idsToUpdate = new int[N];
+ for (int i = 0; i < N; i++) {
+ idsToUpdate[i] = mViews.keyAt(i);
+ }
+ }
+ List<RemoteViews> updatedViews;
+ int[] updatedIds = new int[idsToUpdate.length];
try {
- updatedIds = sService.startListening(mCallbacks, mContextOpPackageName, mHostId,
- updatedViews);
+ updatedViews = sService.startListening(
+ mCallbacks, mContextOpPackageName, mHostId, idsToUpdate, updatedIds).getList();
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
- final int N = updatedIds.length;
+ int N = updatedViews.size();
for (int i = 0; i < N; i++) {
updateAppWidgetView(updatedIds[i], updatedViews.get(i));
}
@@ -206,10 +214,6 @@
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
-
- // This is here because keyguard needs it since it'll be switching users after this call.
- // If it turns out other apps need to call this often, we should re-think how this works.
- clearViews();
}
/**
@@ -418,7 +422,9 @@
* Clear the list of Views that have been created by this AppWidgetHost.
*/
protected void clearViews() {
- mViews.clear();
+ synchronized (mViews) {
+ mViews.clear();
+ }
}
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d762a17..2a7eff8 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -36,6 +36,7 @@
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.Pair;
@@ -1015,6 +1016,8 @@
try {
if (mService != null) {
return mService.factoryReset();
+ } else {
+ SystemProperties.set("persist.bluetooth.factoryreset", "true");
}
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 2dce425..b2288fc 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -136,12 +136,14 @@
}
String vmFlags = "CheckJNI="
+ (vmRuntime.isCheckJniEnabled() ? "true" : "false");
+ boolean isNativeDebuggable = vmRuntime.isNativeDebuggable();
ByteBuffer out = ByteBuffer.allocate(28
+ vmIdent.length() * 2
+ appName.length() * 2
+ instructionSetDescription.length() * 2
- + vmFlags.length() * 2);
+ + vmFlags.length() * 2
+ + 1);
out.order(ChunkHandler.CHUNK_ORDER);
out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
out.putInt(android.os.Process.myPid());
@@ -154,6 +156,7 @@
putString(out, instructionSetDescription);
out.putInt(vmFlags.length());
putString(out, vmFlags);
+ out.put((byte)(isNativeDebuggable ? 1 : 0));
Chunk reply = new Chunk(CHUNK_HELO, out);
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index d84a6fc..d2e820e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -974,6 +974,7 @@
if (mRemoteDevice != null) {
mRemoteDevice.disconnect();
+ mRemoteDevice.unlinkToDeath(this, /*flags*/0);
}
// Only want to fire the onClosed callback once;
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index ddc3fd1..ef5f6d7 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -31,6 +31,7 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.SubmitInfo;
+import android.os.IBinder;
import android.os.RemoteException;
import android.view.Surface;
@@ -53,6 +54,12 @@
mRemoteDevice = remoteDevice;
}
+ public void unlinkToDeath(IBinder.DeathRecipient recipient, int flags) {
+ if (mRemoteDevice.asBinder() != null) {
+ mRemoteDevice.asBinder().unlinkToDeath(recipient, flags);
+ }
+ }
+
public void disconnect() {
try {
mRemoteDevice.disconnect();
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
deleted file mode 100644
index 7acf3f5..0000000
--- a/core/java/android/net/DnsPinger.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.util.Protocol;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Performs a simple DNS "ping" by sending a "server status" query packet to the
- * DNS server. As long as the server replies, we consider it a success.
- * <p>
- * We do not use a simple hostname lookup because that could be cached and the
- * API may not differentiate between a time out and a failure lookup (which we
- * really care about).
- * <p>
- *
- * @hide
- */
-public final class DnsPinger extends Handler {
- private static final boolean DBG = false;
-
- private static final int RECEIVE_POLL_INTERVAL_MS = 200;
- private static final int DNS_PORT = 53;
-
- /** Short socket timeout so we don't block one any 'receive' call */
- private static final int SOCKET_TIMEOUT_MS = 1;
-
- /** Used to generate IDs */
- private static final Random sRandom = new Random();
- private static final AtomicInteger sCounter = new AtomicInteger();
-
- private ConnectivityManager mConnectivityManager = null;
- private final Context mContext;
- private final int mConnectionType;
- private final Handler mTarget;
- private final ArrayList<InetAddress> mDefaultDns;
- private String TAG;
-
- //Invalidates old dns requests upon a cancel
- private AtomicInteger mCurrentToken = new AtomicInteger();
-
- private static final int BASE = Protocol.BASE_DNS_PINGER;
-
- /**
- * Async response packet for dns pings.
- * arg1 is the ID of the ping, also returned by {@link #pingDnsAsync(InetAddress, int, int)}
- * arg2 is the delay, or is negative on error.
- */
- public static final int DNS_PING_RESULT = BASE;
- /** An error code for a {@link #DNS_PING_RESULT} packet */
- public static final int TIMEOUT = -1;
- /** An error code for a {@link #DNS_PING_RESULT} packet */
- public static final int SOCKET_EXCEPTION = -2;
-
- /**
- * Send a new ping via a socket. arg1 is ID, arg2 is timeout, obj is InetAddress to ping
- */
- private static final int ACTION_PING_DNS = BASE + 1;
- private static final int ACTION_LISTEN_FOR_RESPONSE = BASE + 2;
- private static final int ACTION_CANCEL_ALL_PINGS = BASE + 3;
-
- private List<ActivePing> mActivePings = new ArrayList<ActivePing>();
- private int mEventCounter;
-
- private class ActivePing {
- DatagramSocket socket;
- int internalId;
- short packetId;
- int timeout;
- Integer result;
- long start = SystemClock.elapsedRealtime();
- }
-
- /* Message argument for ACTION_PING_DNS */
- private class DnsArg {
- InetAddress dns;
- int seq;
-
- DnsArg(InetAddress d, int s) {
- dns = d;
- seq = s;
- }
- }
-
- public DnsPinger(Context context, String TAG, Looper looper,
- Handler target, int connectionType) {
- super(looper);
- this.TAG = TAG;
- mContext = context;
- mTarget = target;
- mConnectionType = connectionType;
- if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
- throw new IllegalArgumentException("Invalid connectionType in constructor: "
- + connectionType);
- }
- mDefaultDns = new ArrayList<InetAddress>();
- mDefaultDns.add(getDefaultDns());
- mEventCounter = 0;
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case ACTION_PING_DNS:
- DnsArg dnsArg = (DnsArg) msg.obj;
- if (dnsArg.seq != mCurrentToken.get()) {
- break;
- }
- try {
- ActivePing newActivePing = new ActivePing();
- InetAddress dnsAddress = dnsArg.dns;
- newActivePing.internalId = msg.arg1;
- newActivePing.timeout = msg.arg2;
- newActivePing.socket = new DatagramSocket();
- // Set some socket properties
- newActivePing.socket.setSoTimeout(SOCKET_TIMEOUT_MS);
-
- // Try to bind but continue ping if bind fails
- try {
- newActivePing.socket.setNetworkInterface(NetworkInterface.getByName(
- getCurrentLinkProperties().getInterfaceName()));
- } catch (Exception e) {
- loge("sendDnsPing::Error binding to socket " + e);
- }
-
- newActivePing.packetId = (short) sRandom.nextInt();
- byte[] buf = mDnsQuery.clone();
- buf[0] = (byte) (newActivePing.packetId >> 8);
- buf[1] = (byte) newActivePing.packetId;
-
- // Send the DNS query
- DatagramPacket packet = new DatagramPacket(buf,
- buf.length, dnsAddress, DNS_PORT);
- if (DBG) {
- log("Sending a ping " + newActivePing.internalId +
- " to " + dnsAddress.getHostAddress()
- + " with packetId " + newActivePing.packetId + ".");
- }
-
- newActivePing.socket.send(packet);
- mActivePings.add(newActivePing);
- mEventCounter++;
- sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
- RECEIVE_POLL_INTERVAL_MS);
- } catch (IOException e) {
- sendResponse(msg.arg1, -9999, SOCKET_EXCEPTION);
- }
- break;
- case ACTION_LISTEN_FOR_RESPONSE:
- if (msg.arg1 != mEventCounter) {
- break;
- }
- for (ActivePing curPing : mActivePings) {
- try {
- /** Each socket will block for {@link #SOCKET_TIMEOUT_MS} in receive() */
- byte[] responseBuf = new byte[2];
- DatagramPacket replyPacket = new DatagramPacket(responseBuf, 2);
- curPing.socket.receive(replyPacket);
- // Check that ID field matches (we're throwing out the rest of the packet)
- if (responseBuf[0] == (byte) (curPing.packetId >> 8) &&
- responseBuf[1] == (byte) curPing.packetId) {
- curPing.result =
- (int) (SystemClock.elapsedRealtime() - curPing.start);
- } else {
- if (DBG) {
- log("response ID didn't match, ignoring packet");
- }
- }
- } catch (SocketTimeoutException e) {
- // A timeout here doesn't mean anything - squelsh this exception
- } catch (Exception e) {
- if (DBG) {
- log("DnsPinger.pingDns got socket exception: " + e);
- }
- curPing.result = SOCKET_EXCEPTION;
- }
- }
- Iterator<ActivePing> iter = mActivePings.iterator();
- while (iter.hasNext()) {
- ActivePing curPing = iter.next();
- if (curPing.result != null) {
- sendResponse(curPing.internalId, curPing.packetId, curPing.result);
- curPing.socket.close();
- iter.remove();
- } else if (SystemClock.elapsedRealtime() >
- curPing.start + curPing.timeout) {
- sendResponse(curPing.internalId, curPing.packetId, TIMEOUT);
- curPing.socket.close();
- iter.remove();
- }
- }
- if (!mActivePings.isEmpty()) {
- sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
- RECEIVE_POLL_INTERVAL_MS);
- }
- break;
- case ACTION_CANCEL_ALL_PINGS:
- for (ActivePing activePing : mActivePings)
- activePing.socket.close();
- mActivePings.clear();
- break;
- }
- }
-
- /**
- * Returns a list of DNS addresses, coming from either the link properties of the
- * specified connection or the default system DNS if the link properties has no dnses.
- * @return a non-empty non-null list
- */
- public List<InetAddress> getDnsList() {
- LinkProperties curLinkProps = getCurrentLinkProperties();
- if (curLinkProps == null) {
- loge("getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
- return mDefaultDns;
- }
-
- Collection<InetAddress> dnses = curLinkProps.getDnsServers();
- if (dnses == null || dnses.size() == 0) {
- loge("getDns::LinkProps has null dns - returning default");
- return mDefaultDns;
- }
-
- return new ArrayList<InetAddress>(dnses);
- }
-
- /**
- * Send a ping. The response will come via a {@link #DNS_PING_RESULT} to the handler
- * specified at creation.
- * @param dns address of dns server to ping
- * @param timeout timeout for ping
- * @return an ID field, which will also be included in the {@link #DNS_PING_RESULT} message.
- */
- public int pingDnsAsync(InetAddress dns, int timeout, int delay) {
- int id = sCounter.incrementAndGet();
- sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout,
- new DnsArg(dns, mCurrentToken.get())), delay);
- return id;
- }
-
- public void cancelPings() {
- mCurrentToken.incrementAndGet();
- obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget();
- }
-
- private void sendResponse(int internalId, int externalId, int responseVal) {
- if(DBG) {
- log("Responding to packet " + internalId +
- " externalId " + externalId +
- " and val " + responseVal);
- }
- mTarget.sendMessage(obtainMessage(DNS_PING_RESULT, internalId, responseVal));
- }
-
- private LinkProperties getCurrentLinkProperties() {
- if (mConnectivityManager == null) {
- mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- }
-
- return mConnectivityManager.getLinkProperties(mConnectionType);
- }
-
- private InetAddress getDefaultDns() {
- String dns = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.DEFAULT_DNS_SERVER);
- if (dns == null || dns.length() == 0) {
- dns = mContext.getResources().getString(
- com.android.internal.R.string.config_default_dns_server);
- }
- try {
- return NetworkUtils.numericToInetAddress(dns);
- } catch (IllegalArgumentException e) {
- loge("getDefaultDns::malformed default dns address");
- return null;
- }
- }
-
- private static final byte[] mDnsQuery = new byte[] {
- 0, 0, // [0-1] is for ID (will set each time)
- 1, 0, // [2-3] are flags. Set byte[2] = 1 for recursion desired (RD) on. Currently on.
- 0, 1, // [4-5] bytes are for number of queries (QCOUNT)
- 0, 0, // [6-7] unused count field for dns response packets
- 0, 0, // [8-9] unused count field for dns response packets
- 0, 0, // [10-11] unused count field for dns response packets
- 3, 'w', 'w', 'w',
- 6, 'g', 'o', 'o', 'g', 'l', 'e',
- 3, 'c', 'o', 'm',
- 0, // null terminator of address (also called empty TLD)
- 0, 1, // QTYPE, set to 1 = A (host address)
- 0, 1 // QCLASS, set to 1 = IN (internet)
- };
-
- private void log(String s) {
- Log.d(TAG, s);
- }
-
- private void loge(String s) {
- Log.e(TAG, s);
- }
-}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index e555fa4..29291ca 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -19,11 +19,9 @@
import android.Manifest;
import android.Manifest.permission;
import android.annotation.Nullable;
-import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
@@ -69,12 +67,32 @@
*/
public final String mConfigurationActivityClassName;
+ /**
+ * Optional class name of the scoring service we can bind to. Null if none is set.
+ */
+ public final String mScoringServiceClassName;
+
public NetworkScorerAppData(String packageName, int packageUid, CharSequence scorerName,
- @Nullable String configurationActivityClassName) {
+ @Nullable String configurationActivityClassName,
+ @Nullable String scoringServiceClassName) {
mScorerName = scorerName;
mPackageName = packageName;
mPackageUid = packageUid;
mConfigurationActivityClassName = configurationActivityClassName;
+ mScoringServiceClassName = scoringServiceClassName;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("NetworkScorerAppData{");
+ sb.append("mPackageName='").append(mPackageName).append('\'');
+ sb.append(", mPackageUid=").append(mPackageUid);
+ sb.append(", mScorerName=").append(mScorerName);
+ sb.append(", mConfigurationActivityClassName='").append(mConfigurationActivityClassName)
+ .append('\'');
+ sb.append(", mScoringServiceClassName='").append(mScoringServiceClassName).append('\'');
+ sb.append('}');
+ return sb.toString();
}
}
@@ -128,18 +146,27 @@
Intent intent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE);
intent.setPackage(receiverInfo.packageName);
List<ResolveInfo> configActivities = pm.queryIntentActivities(intent, 0 /* flags */);
- if (!configActivities.isEmpty()) {
+ if (configActivities != null && !configActivities.isEmpty()) {
ActivityInfo activityInfo = configActivities.get(0).activityInfo;
if (activityInfo != null) {
configurationActivityClassName = activityInfo.name;
}
}
+ // Find the scoring service class we can bind to, if any.
+ String scoringServiceClassName = null;
+ Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
+ serviceIntent.setPackage(receiverInfo.packageName);
+ ResolveInfo resolveServiceInfo = pm.resolveService(serviceIntent, 0 /* flags */);
+ if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
+ scoringServiceClassName = resolveServiceInfo.serviceInfo.name;
+ }
+
// NOTE: loadLabel will attempt to load the receiver's label and fall back to the
// app label if none is present.
scorers.add(new NetworkScorerAppData(receiverInfo.packageName,
receiverInfo.applicationInfo.uid, receiverInfo.loadLabel(pm),
- configurationActivityClassName));
+ configurationActivityClassName, scoringServiceClassName));
}
return scorers;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8e2dd6b..c452837 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -448,19 +448,41 @@
public abstract Timer getForegroundActivityTimer();
public abstract Timer getBluetoothScanTimer();
- // Time this uid has any processes in the top state.
+ // Note: the following times are disjoint. They can be added together to find the
+ // total time a uid has had any processes running at all.
+
+ /**
+ * Time this uid has any processes in the top state (or above such as persistent).
+ */
public static final int PROCESS_STATE_TOP = 0;
- // Time this uid has any process with a started out bound foreground service.
+ /**
+ * Time this uid has any process with a started out bound foreground service, but
+ * none in the "top" state.
+ */
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 1;
- // Time this uid has any process that is top while the device is sleeping.
+ /**
+ * Time this uid has any process that is top while the device is sleeping, but none
+ * in the "foreground service" or better state.
+ */
public static final int PROCESS_STATE_TOP_SLEEPING = 2;
- // Time this uid has any process in an active foreground state.
+ /**
+ * Time this uid has any process in an active foreground state, but none in the
+ * "top sleeping" or better state.
+ */
public static final int PROCESS_STATE_FOREGROUND = 3;
- // Time this uid has any process in an active background state.
+ /**
+ * Time this uid has any process in an active background state, but none in the
+ * "foreground" or better state.
+ */
public static final int PROCESS_STATE_BACKGROUND = 4;
- // Time this uid has any processes running at all.
+ /**
+ * Time this uid has any processes that are sitting around cached, not in one of the
+ * other active states.
+ */
public static final int PROCESS_STATE_CACHED = 5;
- // Total number of process states we track.
+ /**
+ * Total number of process states we track.
+ */
public static final int NUM_PROCESS_STATE = 6;
static final String[] PROCESS_STATE_NAMES = {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 24a6cdf..68b0a9f 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -328,11 +328,6 @@
*/
void setDnsServersForNetwork(int netId, in String[] servers, String domains);
- /**
- * Flush the DNS cache associated with the specified network.
- */
- void flushNetworkDnsCache(int netId);
-
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
void setFirewallInterfaceRule(String iface, boolean allow);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b723ffa8..b95d830 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16954,7 +16954,7 @@
}
} else if (cache != null) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
- if (layerType == LAYER_TYPE_NONE) {
+ if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
// no layer paint, use temporary paint to draw bitmap
Paint cachePaint = parent.mCachePaint;
if (cachePaint == null) {
@@ -16966,13 +16966,12 @@
canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
} else {
// use layer paint to draw the bitmap, merging the two alphas, but also restore
- int layerPaintAlpha = mLayerPaint != null ? mLayerPaint.getAlpha() : 255;
- if (mLayerPaint == null && alpha < 1) {
- mLayerPaint = new Paint();
+ int layerPaintAlpha = mLayerPaint.getAlpha();
+ if (alpha < 1) {
mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
}
canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
- if (mLayerPaint != null) {
+ if (alpha < 1) {
mLayerPaint.setAlpha(layerPaintAlpha);
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 1482111..02d2a8b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -328,36 +328,6 @@
// Action arguments
/**
- * Argument for specifying index of {@link android.text.style.ClickableSpan} the click action is
- * related to.
- * <p>
- * <strong>Type:</strong> int<br>
- * <strong>Actions:</strong>
- * {@link AccessibilityAction#ACTION_CLICK}
- * </p>
- *
- * @see AccessibilityAction#ACTION_CLICK
- */
- public static final String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT =
- "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
-
- /**
- * Argument for specifying index of character in the text which contains
- * {@link android.text.style.ClickableSpan} the click action is
- * related to. If there is more than one {@link android.text.style.ClickableSpan} assigned for
- * the range the character is in only the first span would be clicked.
- * <p>
- * <strong>Type:</strong> int<br>
- * <strong>Actions:</strong>
- * {@link AccessibilityAction#ACTION_CLICK}
- * </p>
- *
- * @see AccessibilityAction#ACTION_CLICK
- */
- public static final String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT =
- "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
-
- /**
* Argument for which movement granularity to be used when traversing the node text.
* <p>
* <strong>Type:</strong> int<br>
@@ -3391,33 +3361,6 @@
/**
* Action that clicks on the node info.
- *
- * <p>
- * If a specific {@link android.text.style.ClickableSpan} within node's text content is
- * supposed to be clicked, then one of {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT} or
- * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} arguments should be specified.
- * If both arguments are set {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} would
- * be ignored.<br>
- *
- * {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT} specifies index of corresponding
- * {@link android.text.style.ClickableSpan} in {@link android.text.SpannableString}.<br>
- *
- * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} specifies index of character
- * that could contain one or more spans.
- * </p>
- *
- * <p>
- * <strong>Optional arguments:</strong>
- * {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT},
- * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT}<br>
- * <strong>Example:</strong> Perform click on 3rd {@link android.text.style.ClickableSpan}
- * inside {@link android.text.SpannableString} in node's text.
- * <code><pre><p>
- * Bundle arguments = new Bundle();
- * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT, 3);
- * info.performAction(AccessibilityAction.ACTION_CLICK.getId(), arguments);
- * </code></pre></p>
- * </p>
*/
public static final AccessibilityAction ACTION_CLICK =
new AccessibilityAction(
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 6879901..1ce80434 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1307,6 +1307,12 @@
void focusInLocked(View view) {
if (DEBUG) Log.v(TAG, "focusIn: " + dumpViewInfo(view));
+ if (view != null && view.isTemporarilyDetached()) {
+ // This is a request from a view that is temporarily detached from a window.
+ if (DEBUG) Log.v(TAG, "Temporarily detached view, ignoring");
+ return;
+ }
+
if (mCurRootView != view.getRootView()) {
// This is a request from a window that isn't in the window with
// IME focus, so ignore it.
@@ -1332,6 +1338,7 @@
// whenever we go into touch mode, so it ends up hiding
// at times when we don't really want it to. For now it
// seems better to just turn it all off.
+ // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
if (false && view.hasWindowFocus()) {
mNextServedView = null;
scheduleCheckFocusLocked(view);
@@ -1348,7 +1355,7 @@
synchronized (mH) {
if (DEBUG) Log.v(TAG, "onViewDetachedFromWindow: view=" + dumpViewInfo(view)
+ " mServedView=" + dumpViewInfo(mServedView));
- if (mServedView == view && view.hasWindowFocus()) {
+ if (mServedView == view) {
mNextServedView = null;
scheduleCheckFocusLocked(view);
}
@@ -2315,6 +2322,7 @@
sb.append(",focus=" + view.hasFocus());
sb.append(",windowFocus=" + view.hasWindowFocus());
sb.append(",window=" + view.getWindowToken());
+ sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
return sb.toString();
}
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index cde7604..66896ab 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -430,9 +430,11 @@
* Sets whether to show the week number.
*
* @param showWeekNumber True to show the week number.
+ * @deprecated No longer used by Material-style CalendarView.
*
* @attr ref android.R.styleable#CalendarView_showWeekNumber
*/
+ @Deprecated
public void setShowWeekNumber(boolean showWeekNumber) {
mDelegate.setShowWeekNumber(showWeekNumber);
}
@@ -441,9 +443,11 @@
* Gets whether to show the week number.
*
* @return True if showing the week number.
+ * @deprecated No longer used by Material-style CalendarView.
*
* @attr ref android.R.styleable#CalendarView_showWeekNumber
*/
+ @Deprecated
public boolean getShowWeekNumber() {
return mDelegate.getShowWeekNumber();
}
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 442fb33..f540479 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -404,7 +404,7 @@
@Override
public int getUnfocusedMonthDateColor() {
- return mFocusedMonthDateColor;
+ return mUnfocusedMonthDateColor;
}
@Override
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index c471cf3..0d8d8ed 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1495,7 +1495,7 @@
*
* @param anchor the view on which the popup window must be anchored
* @param outParams the layout parameters used to display the drop down
- * @param xOffset absolute horizontal offset from the top of the anchor
+ * @param xOffset absolute horizontal offset from the left of the anchor
* @param yOffset absolute vertical offset from the top of the anchor
* @param gravity horizontal gravity specifying popup alignment
* @return true if the popup is translated upwards to fit on screen
@@ -1524,6 +1524,8 @@
// Let the window manager know to align the top to y.
outParams.gravity = Gravity.LEFT | Gravity.TOP;
+ outParams.width = width;
+ outParams.height = height;
final int[] screenLocation = mTmpScreenLocation;
anchor.getLocationOnScreen(screenLocation);
@@ -1531,100 +1533,154 @@
final Rect displayFrame = new Rect();
anchor.getWindowVisibleDisplayFrame(displayFrame);
- boolean onTop = false;
+ // First, attempt to fit the popup vertically without resizing.
+ final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
+ anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
+ displayFrame.bottom, false);
- final View root = anchor.getRootView();
- final int screenY = screenLocation[1] + anchorHeight + yOffset;
- final boolean tooFarDown = screenY + height > displayFrame.bottom;
- final boolean tooFarRight = outParams.x + width > root.getWidth();
- if (tooFarDown || tooFarRight) {
- // If the popup extends beyond the visible area, try to scroll the
- // parent so that it is fully visible.
- if (mAllowScrollingAnchorParent) {
- final int scrollX = anchor.getScrollX();
- final int scrollY = anchor.getScrollY();
- final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
- scrollY + height + anchorHeight + yOffset);
- anchor.requestRectangleOnScreen(r, true);
- }
+ // Next, attempt to fit the popup horizontally without resizing.
+ final boolean fitsHorizontal = tryFitHorizontal(outParams, xOffset, width,
+ anchorWidth, drawingLocation[0], screenLocation[0], displayFrame.left,
+ displayFrame.right, false);
- // Update for the new anchor position.
- anchor.getLocationInWindow(drawingLocation);
- outParams.x = drawingLocation[0] + xOffset;
- outParams.y = drawingLocation[1] + anchorHeight + yOffset;
+ // If the popup still doesn't fit, attempt to scroll the parent.
+ if (!fitsVertical || !fitsHorizontal) {
+ final int scrollX = anchor.getScrollX();
+ final int scrollY = anchor.getScrollY();
+ final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
+ scrollY + height + anchorHeight + yOffset);
+ if (mAllowScrollingAnchorParent && anchor.requestRectangleOnScreen(r, true)) {
+ // Reset for the new anchor position.
+ anchor.getLocationInWindow(drawingLocation);
+ outParams.x = drawingLocation[0] + xOffset;
+ outParams.y = drawingLocation[1] + anchorHeight + yOffset;
- // Preserve the gravity adjustment.
- if (hgrav == Gravity.RIGHT) {
- outParams.x -= width - anchorWidth;
- }
-
- final int newScreenY = screenLocation[1] + anchorHeight + yOffset;
- final boolean stillTooFarDown = newScreenY + height > displayFrame.bottom;
- if (stillTooFarDown) {
- // If the popup is still too far down, re-evaluate the space
- // available and decide whether the pop-up will go above or
- // below the anchor.
- anchor.getLocationOnScreen(screenLocation);
-
- final int below = displayFrame.bottom - screenLocation[1] - anchorHeight - yOffset;
- final int above = screenLocation[1] - displayFrame.top + yOffset;
- onTop = above > below;
-
- if (onTop) {
- // Move everything up.
- if (mOverlapAnchor) {
- yOffset += anchorHeight;
- }
- outParams.y = drawingLocation[1] - height + yOffset;
+ // Preserve the gravity adjustment.
+ if (hgrav == Gravity.RIGHT) {
+ outParams.x -= width - anchorWidth;
}
}
+
+ // Try to fit the popup again and allowing resizing.
+ tryFitVertical(outParams, yOffset, height, anchorHeight, drawingLocation[1],
+ screenLocation[1], displayFrame.top, displayFrame.bottom, mClipToScreen);
+ tryFitHorizontal(outParams, xOffset, width, anchorWidth, drawingLocation[0],
+ screenLocation[0], displayFrame.left, displayFrame.right, mClipToScreen);
}
- if (mClipToScreen) {
- // Use screen coordinates for comparison against display frame.
- final int winOffsetX = screenLocation[0] - drawingLocation[0];
- final int winOffsetY = screenLocation[1] - drawingLocation[1];
- outParams.x += winOffsetX;
- outParams.y += winOffsetY;
+ // Return whether the popup's top edge is above the anchor's top edge.
+ return outParams.y < drawingLocation[1];
+ }
- final int right = outParams.x + width;
- if (right > displayFrame.right) {
- // The popup is too far right, move it back in.
- outParams.x -= right - displayFrame.right;
- }
-
- if (outParams.x < displayFrame.left) {
- // The popup is too far left, move it back in and clip if it's
- // still too large.
- outParams.x = displayFrame.left;
-
- final int displayFrameWidth = displayFrame.width();
- width = Math.min(width, displayFrameWidth);
- }
-
- final int bottom = outParams.y + height;
- if (bottom > displayFrame.bottom) {
- // The popup is too far down, move it back in.
- outParams.y -= bottom - displayFrame.bottom;
- }
-
- if (outParams.y < displayFrame.top) {
- // The popup is too far up, move it back in and clip if
- // it's still too large.
- outParams.y = displayFrame.top;
-
- final int displayFrameHeight = displayFrame.height();
- height = Math.min(height, displayFrameHeight);
- }
-
- outParams.x -= winOffsetX;
- outParams.y -= winOffsetY;
+ private boolean tryFitVertical(@NonNull LayoutParams outParams, int yOffset, int height,
+ int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
+ int displayFrameBottom, boolean allowResize) {
+ final int anchorTopInScreen = screenLocationY + anchorHeight + yOffset;
+ final int spaceBelow = displayFrameBottom - anchorTopInScreen;
+ if (height <= spaceBelow) {
+ return true;
}
- outParams.width = width;
+ final int spaceAbove = displayFrameTop + anchorTopInScreen - anchorHeight;
+ if (height <= spaceAbove) {
+ // Move everything up.
+ if (mOverlapAnchor) {
+ yOffset += anchorHeight;
+ }
+ outParams.y = drawingLocationY - height + yOffset;
+
+ return true;
+ }
+
+ if (positionInDisplayVertical(outParams, height, drawingLocationY, screenLocationY,
+ displayFrameTop, displayFrameBottom, allowResize)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean positionInDisplayVertical(@NonNull LayoutParams outParams, int height,
+ int drawingLocationY, int screenLocationY, int displayFrameTop, int displayFrameBottom,
+ boolean canResize) {
+ boolean fitsInDisplay = true;
+
+ final int winOffsetY = screenLocationY - drawingLocationY;
+ outParams.y += winOffsetY;
outParams.height = height;
- return onTop;
+ final int bottom = outParams.y + height;
+ if (bottom > displayFrameBottom) {
+ // The popup is too far down, move it back in.
+ outParams.y -= bottom - displayFrameBottom;
+ }
+
+ if (outParams.y < displayFrameTop) {
+ // The popup is too far up, move it back in and clip if
+ // it's still too large.
+ outParams.y = displayFrameTop;
+
+ final int displayFrameHeight = displayFrameBottom - displayFrameTop;
+ if (canResize && height > displayFrameHeight) {
+ outParams.height = displayFrameHeight;
+ } else {
+ fitsInDisplay = false;
+ }
+ }
+
+ outParams.y -= winOffsetY;
+
+ return fitsInDisplay;
+ }
+
+ private boolean tryFitHorizontal(@NonNull LayoutParams outParams, int xOffset, int width,
+ int anchorWidth, int drawingLocationX, int screenLocationX, int displayFrameLeft,
+ int displayFrameRight, boolean allowResize) {
+ final int anchorLeftInScreen = screenLocationX + xOffset;
+ final int spaceRight = displayFrameRight - anchorLeftInScreen;
+ if (width <= spaceRight) {
+ return true;
+ }
+
+ if (positionInDisplayHorizontal(outParams, width, drawingLocationX, screenLocationX,
+ displayFrameLeft, displayFrameRight, allowResize)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean positionInDisplayHorizontal(@NonNull LayoutParams outParams, int width,
+ int drawingLocationX, int screenLocationX, int displayFrameLeft, int displayFrameRight,
+ boolean canResize) {
+ boolean fitsInDisplay = true;
+
+ // Use screen coordinates for comparison against display frame.
+ final int winOffsetX = screenLocationX - drawingLocationX;
+ outParams.x += winOffsetX;
+
+ final int right = outParams.x + width;
+ if (right > displayFrameRight) {
+ // The popup is too far right, move it back in.
+ outParams.x -= right - displayFrameRight;
+ }
+
+ if (outParams.x < displayFrameLeft) {
+ // The popup is too far left, move it back in and clip if it's
+ // still too large.
+ outParams.x = displayFrameLeft;
+
+ final int displayFrameWidth = displayFrameRight - displayFrameLeft;
+ if (canResize && width > displayFrameWidth) {
+ outParams.width = displayFrameWidth;
+ } else {
+ fitsInDisplay = false;
+ }
+ }
+
+ outParams.x -= winOffsetX;
+
+ return fitsInDisplay;
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3b7b16d..4483b7ba 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9210,52 +9210,12 @@
private boolean performAccessibilityActionClick(Bundle arguments) {
boolean handled = false;
- boolean processed = false;
if (!isEnabled()) {
return false;
}
- if (arguments != null && arguments.containsKey(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT)) {
- int spanIndex = arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT, -1);
- if (spanIndex >= 0 && hasSpannableText()) {
- ClickableSpan[] spans = ((Spannable) mText).getSpans(0,
- mText.length(), ClickableSpan.class);
- if (spans != null && spans.length > spanIndex && spans[spanIndex] != null) {
- // Simulate View.onTouchEvent for an ACTION_UP event
- if (isFocusable() && !isFocused()) {
- requestFocus();
- }
- spans[spanIndex].onClick(this);
- handled = true;
- }
- }
- processed = true;
- }
-
- if (!processed && arguments != null && arguments.containsKey(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT)) {
- int characterIndex = arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT, -1);
- if (characterIndex >= 0 && hasSpannableText()) {
- ClickableSpan[] spans = ((Spannable) mText).getSpans(characterIndex,
- characterIndex, ClickableSpan.class);
- // click only on the first span to keep parity with onTouch() implementation
- if (spans != null && spans.length > 0 && spans[0] != null) {
- // Simulate View.onTouchEvent for an ACTION_UP event
- if (isFocusable() && !isFocused()) {
- requestFocus();
- }
- spans[0].onClick(this);
- handled = true;
- }
- }
- processed = true;
- }
-
- if (!processed && (isClickable() || isLongClickable())) {
+ if (isClickable() || isLongClickable()) {
// Simulate View.onTouchEvent for an ACTION_UP event
if (isFocusable() && !isFocused()) {
requestFocus();
diff --git a/core/java/com/android/internal/app/procstats/SparseMappingTable.java b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
index 64c49a2..7252276 100644
--- a/core/java/com/android/internal/app/procstats/SparseMappingTable.java
+++ b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
@@ -28,7 +28,7 @@
/**
* Class that contains a set of tables mapping byte ids to long values.
- *
+ *
* This class is used to store the ProcessStats data. This data happens to be
* a set of very sparse tables, that is mostly append or overwrite, with infrequent
* resets of the data.
@@ -59,11 +59,11 @@
// Where the "index into array" part of the data appears in an offset integer.
private static final int INDEX_SHIFT = 16;
private static final int INDEX_MASK = 0xffff;
-
+
private int mSequence;
private int mNextIndex;
private final ArrayList<long[]> mLongs = new ArrayList<long[]>();
-
+
/**
* A table of data as stored in a SparseMappingTable.
*/
@@ -377,20 +377,24 @@
// since we were created or reset.
if (mSequence == UNINITIALIZED_SEQUENCE) {
logOrThrow("mSequence == UNINITIALIZED_SEQUENCE in"
- + " SparseMappingTable.Table. mParent.mSequence=" + mParent.mSequence);
+ + " SparseMappingTable.Table. -- "
+ + dumpInternalState());
+ return;
}
// Assert that our sequence number matches mParent's. If it isn't that means
- // we have been reset and our
+ // we have been reset and our
if (mSequence != mParent.mSequence) {
if (mSequence < mParent.mSequence) {
logOrThrow("Sequence mismatch. SparseMappingTable.resetTable()"
+ " called but not Table.resetTable() -- "
+ dumpInternalState());
+ return;
} else if (mSequence > mParent.mSequence) {
logOrThrow("Sequence mismatch. Table.resetTable()"
+ " called but not SparseMappingTable.resetTable() -- "
+ dumpInternalState());
+ return;
}
}
}
@@ -423,7 +427,7 @@
/**
* Check that all the keys are valid locations in the long arrays.
- *
+ *
* If any aren't, log it and return false. Else return true.
*/
private boolean validateKeys(boolean log) {
@@ -580,7 +584,7 @@
i++;
}
}
-
+
/**
* Extract the id from a key.
*/
@@ -611,7 +615,7 @@
* this is a debug build.)
*/
private static void logOrThrow(String message) {
- logOrThrow(message, null);
+ logOrThrow(message, new RuntimeException("Stack trace"));
}
/**
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 5a195cb..4260e50 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -33,8 +33,8 @@
//
// for AppWidgetHost
//
- int[] startListening(IAppWidgetHost host, String callingPackage, int hostId,
- out List<RemoteViews> updatedViews);
+ ParceledListSlice startListening(IAppWidgetHost host, String callingPackage, int hostId,
+ in int[] appWidgetIds, out int[] updatedIds);
void stopListening(String callingPackage, int hostId);
int allocateAppWidgetId(String callingPackage, int hostId);
void deleteAppWidgetId(String callingPackage, int appWidgetId);
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java
index 7a04080..3c1d2d6 100644
--- a/core/java/com/android/internal/util/FastXmlSerializer.java
+++ b/core/java/com/android/internal/util/FastXmlSerializer.java
@@ -28,6 +28,7 @@
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
@@ -38,14 +39,14 @@
*/
public class FastXmlSerializer implements XmlSerializer {
private static final String ESCAPE_TABLE[] = new String[] {
- null, null, null, null, null, null, null, null, // 0-7
- null, null, null, null, null, null, null, null, // 8-15
- null, null, null, null, null, null, null, null, // 16-23
- null, null, null, null, null, null, null, null, // 24-31
- null, null, """, null, null, null, "&", null, // 32-39
- null, null, null, null, null, null, null, null, // 40-47
- null, null, null, null, null, null, null, null, // 48-55
- null, null, null, null, "<", null, ">", null, // 56-63
+ "�", "", "", "", "", "", "", "", // 0-7
+ "", "	", " ", "", "", " ", "", "", // 8-15
+ "", "", "", "", "", "", "", "", // 16-23
+ "", "", "", "", "", "", "", "", // 24-31
+ null, null, """, null, null, null, "&", null, // 32-39
+ null, null, null, null, null, null, null, null, // 40-47
+ null, null, null, null, null, null, null, null, // 48-55
+ null, null, null, null, "<", null, ">", null, // 56-63
};
private static final int BUFFER_LEN = 8192;
@@ -310,7 +311,9 @@
throw new IllegalArgumentException();
if (true) {
try {
- mCharset = Charset.forName(encoding).newEncoder();
+ mCharset = Charset.forName(encoding).newEncoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
} catch (IllegalCharsetNameException e) {
throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
encoding).initCause(e));
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2018e76..6e9830e 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -65,12 +65,12 @@
EGLContext ctx = eglGetCurrentContext();
if (dpy == EGL_NO_DISPLAY) {
- ALOGE("isProtectedSurface: invalid current EGLDisplay");
+ ALOGI("isProtectedSurface: invalid current EGLDisplay");
return false;
}
if (ctx == EGL_NO_CONTEXT) {
- ALOGE("isProtectedSurface: invalid current EGLContext");
+ ALOGI("isProtectedSurface: invalid current EGLContext");
return false;
}
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 9ab62cc..e7aca78 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -23,10 +23,10 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.os.UserHandle;
import android.test.InstrumentationTestCase;
-import android.util.Pair;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
@@ -58,25 +58,26 @@
public void testGetAllValidScorers() throws Exception {
// Package 1 - Valid scorer.
- Pair<ResolveInfo, ResolveInfo> package1 = buildResolveInfo("package1", 1, true, true,
- false);
+ ResolveInfoHolder package1 = buildResolveInfo("package1", 1, true, true, false, false);
// Package 2 - Receiver does not have BROADCAST_NETWORK_PRIVILEGED permission.
- Pair<ResolveInfo, ResolveInfo> package2 = buildResolveInfo("package2", 2, false, true,
- false);
+ ResolveInfoHolder package2 = buildResolveInfo("package2", 2, false, true, false, false);
// Package 3 - App does not have SCORE_NETWORKS permission.
- Pair<ResolveInfo, ResolveInfo> package3 = buildResolveInfo("package3", 3, true, false,
- false);
+ ResolveInfoHolder package3 = buildResolveInfo("package3", 3, true, false, false, false);
// Package 4 - Valid scorer w/ optional config activity.
- Pair<ResolveInfo, ResolveInfo> package4 = buildResolveInfo("package4", 4, true, true, true);
+ ResolveInfoHolder package4 = buildResolveInfo("package4", 4, true, true, true, false);
- List<Pair<ResolveInfo, ResolveInfo>> scorers = new ArrayList<>();
+ // Package 5 - Valid scorer w/ optional service to bind to.
+ ResolveInfoHolder package5 = buildResolveInfo("package5", 5, true, true, false, true);
+
+ List<ResolveInfoHolder> scorers = new ArrayList<>();
scorers.add(package1);
scorers.add(package2);
scorers.add(package3);
scorers.add(package4);
+ scorers.add(package5);
setScorers(scorers);
Iterator<NetworkScorerAppData> result =
@@ -94,14 +95,20 @@
assertEquals(4, next.mPackageUid);
assertEquals(".ConfigActivity", next.mConfigurationActivityClassName);
+ assertTrue(result.hasNext());
+ next = result.next();
+ assertEquals("package5", next.mPackageName);
+ assertEquals(5, next.mPackageUid);
+ assertEquals(".ScoringService", next.mScoringServiceClassName);
+
assertFalse(result.hasNext());
}
- private void setScorers(List<Pair<ResolveInfo, ResolveInfo>> scorers) {
+ private void setScorers(List<ResolveInfoHolder> scorers) {
List<ResolveInfo> receivers = new ArrayList<>();
- for (final Pair<ResolveInfo, ResolveInfo> scorer : scorers) {
- receivers.add(scorer.first);
- if (scorer.second != null) {
+ for (final ResolveInfoHolder scorer : scorers) {
+ receivers.add(scorer.scorerResolveInfo);
+ if (scorer.configActivityResolveInfo != null) {
// This scorer has a config activity.
Mockito.when(mMockPm.queryIntentActivities(
Mockito.argThat(new ArgumentMatcher<Intent>() {
@@ -110,10 +117,26 @@
Intent intent = (Intent) object;
return NetworkScoreManager.ACTION_CUSTOM_ENABLE.equals(
intent.getAction())
- && scorer.first.activityInfo.packageName.equals(
+ && scorer.scorerResolveInfo.activityInfo.packageName.equals(
intent.getPackage());
}
- }), Mockito.eq(0))).thenReturn(Collections.singletonList(scorer.second));
+ }), Mockito.eq(0))).thenReturn(
+ Collections.singletonList(scorer.configActivityResolveInfo));
+ }
+
+ if (scorer.serviceResolveInfo != null) {
+ // This scorer has a service to bind to
+ Mockito.when(mMockPm.resolveService(
+ Mockito.argThat(new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Object object) {
+ Intent intent = (Intent) object;
+ return NetworkScoreManager.ACTION_SCORE_NETWORKS.equals(
+ intent.getAction())
+ && scorer.scorerResolveInfo.activityInfo.packageName.equals(
+ intent.getPackage());
+ }
+ }), Mockito.eq(0))).thenReturn(scorer.serviceResolveInfo);
}
}
@@ -128,9 +151,9 @@
.thenReturn(receivers);
}
- private Pair<ResolveInfo, ResolveInfo> buildResolveInfo(String packageName, int packageUid,
- boolean hasReceiverPermission, boolean hasScorePermission, boolean hasConfigActivity)
- throws Exception {
+ private ResolveInfoHolder buildResolveInfo(String packageName, int packageUid,
+ boolean hasReceiverPermission, boolean hasScorePermission, boolean hasConfigActivity,
+ boolean hasServiceInfo) throws Exception {
Mockito.when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
.thenReturn(hasScorePermission ?
PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
@@ -150,6 +173,27 @@
configActivityInfo.activityInfo = new ActivityInfo();
configActivityInfo.activityInfo.name = ".ConfigActivity";
}
- return Pair.create(resolveInfo, configActivityInfo);
+
+ ResolveInfo serviceInfo = null;
+ if (hasServiceInfo) {
+ serviceInfo = new ResolveInfo();
+ serviceInfo.serviceInfo = new ServiceInfo();
+ serviceInfo.serviceInfo.name = ".ScoringService";
+ }
+
+ return new ResolveInfoHolder(resolveInfo, configActivityInfo, serviceInfo);
+ }
+
+ private static class ResolveInfoHolder {
+ final ResolveInfo scorerResolveInfo;
+ final ResolveInfo configActivityResolveInfo;
+ final ResolveInfo serviceResolveInfo;
+
+ public ResolveInfoHolder(ResolveInfo scorerResolveInfo,
+ ResolveInfo configActivityResolveInfo, ResolveInfo serviceResolveInfo) {
+ this.scorerResolveInfo = scorerResolveInfo;
+ this.configActivityResolveInfo = configActivityResolveInfo;
+ this.serviceResolveInfo = serviceResolveInfo;
+ }
}
}
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index 43a61e3..d491ec4 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -515,7 +515,7 @@
public void testGetPrintServices() throws Exception {
List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId);
- assertTrue(printServices.size() >= 2);
+ assertTrue(printServices.size() >= 1);
printServices = mIPrintManager.getPrintServices(0, mUserId);
assertEquals(printServices, null);
diff --git a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
index 5f36c2d..3cef336 100644
--- a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
@@ -16,16 +16,32 @@
package com.android.internal.util;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.util.Xml;
+
import junit.framework.TestCase;
+import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
/**
* Tests for {@link FastXmlSerializer}
*/
+@SmallTest
public class FastXmlSerializerTest extends TestCase {
+ private static final String TAG = "FastXmlSerializerTest";
+
+ private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH TRUE.
+
+ private static final String ROOT_TAG = "root";
+ private static final String ATTR = "attr";
+
public void testEmptyText() throws Exception {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
@@ -44,4 +60,93 @@
assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<string name=\"meow\"></string>\n", stream.toString());
}
+
+ private boolean checkPreserved(String description, String str) {
+ boolean ok = true;
+ byte[] data;
+ try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ final XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(baos, StandardCharsets.UTF_16.name());
+ out.startDocument(null, true);
+
+ out.startTag(null, ROOT_TAG);
+ out.attribute(null, ATTR, str);
+ out.text(str);
+ out.endTag(null, ROOT_TAG);
+
+ out.endDocument();
+ baos.flush();
+ data = baos.toByteArray();
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to serialize: " + description, e);
+ return false;
+ }
+
+ if (ENABLE_DUMP) {
+ Log.d(TAG, "Dump:");
+ Log.d(TAG, new String(data));
+ }
+
+ try (final ByteArrayInputStream baos = new ByteArrayInputStream(data)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(baos, StandardCharsets.UTF_16.name());
+
+ int type;
+ String tag = null;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG) {
+ tag = parser.getName();
+ if (ROOT_TAG.equals(tag)) {
+ String read = parser.getAttributeValue(null, ATTR);
+ if (!str.equals(read)) {
+ Log.e(TAG, "Attribute not preserved: " + description
+ + " input=\"" + str + "\", but read=\"" + read + "\"");
+ ok = false;
+ }
+ }
+ }
+ if (type == XmlPullParser.TEXT && ROOT_TAG.equals(tag)) {
+ String read = parser.getText();
+ if (!str.equals(parser.getText())) {
+ Log.e(TAG, "Text not preserved: " + description
+ + " input=\"" + str + "\", but read=\"" + read + "\"");
+ ok = false;
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to parse: " + description, e);
+ return false;
+ }
+ return ok;
+ }
+
+ private boolean check(String description, String str) throws Exception {
+ boolean ok = false;
+ ok |= checkPreserved(description, str);
+ ok |= checkPreserved(description + " wrapped with spaces" ," " + str + " ");
+ return ok;
+ }
+
+ @LargeTest
+ public void testAllCharacters() throws Exception {
+ boolean ok = true;
+ for (int i = 0; i < 0xffff; i++) {
+ if (0xd800 <= i && i <= 0xdfff) {
+ // Surrogate pair characters.
+ continue;
+ }
+ ok &= check("char: " + i, String.valueOf((char) i));
+ }
+ // Dangling surrogate pairs. We can't preserve them.
+ assertFalse(check("+ud800", "\ud800"));
+ assertFalse(check("+udc00", "\udc00"));
+
+ for (int i = 0xd800; i < 0xdc00; i ++) {
+ for (int j = 0xdc00; j < 0xe000; j++) {
+ ok &= check("char: " + i, String.valueOf((char) i) + String.valueOf((char) j));
+ }
+ }
+ assertTrue("Some tests failed. See logcat for details.", ok);
+ }
}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index e3639ec..f4c5b53 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -108,6 +108,6 @@
endif
.PHONY: fontchain_lint
-fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
+fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml $(PRODUCT_OUT)/system.img
PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
python $(FONTCHAIN_LINTER) $(TARGET_OUT) $(CHECK_EMOJI) external/unicode
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index f43bf86..5fb8425 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -809,10 +809,6 @@
Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
.build();
renderer.renderGlop(state, glop);
-
- if (op.destroy) {
- renderer.renderState().layerPool().putOrDelete(buffer);
- }
}
}
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 20f102b..3c302b3 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -37,6 +37,10 @@
return buffer;
}
+void BakedOpRenderer::recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) {
+ mRenderState.layerPool().putOrDelete(offscreenBuffer);
+}
+
void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 1b4065a..62bc564 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -69,6 +69,7 @@
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect);
void endFrame(const Rect& repaintRect);
WARN_UNUSED_RESULT OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer);
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect);
void endLayer();
WARN_UNUSED_RESULT OffscreenBuffer* copyToLayer(const Rect& area);
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index e418227..039ab6b 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -86,6 +86,7 @@
*/
template <typename StaticDispatcher, typename Renderer>
void replayBakedOps(Renderer& renderer) {
+ std::vector<OffscreenBuffer*> temporaryLayers;
finishDefer();
/**
* Defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
@@ -129,6 +130,7 @@
} else if (!layer.empty()) {
// save layer - skip entire layer if empty (in which case, LayerOp has null layer).
layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height);
+ temporaryLayers.push_back(layer.offscreenBuffer);
GL_CHECKPOINT(MODERATE);
layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
GL_CHECKPOINT(MODERATE);
@@ -145,6 +147,10 @@
GL_CHECKPOINT(MODERATE);
renderer.endFrame(fbo0.repaintRect);
}
+
+ for (auto& temporaryLayer : temporaryLayers) {
+ renderer.recycleTemporaryLayer(temporaryLayer);
+ }
}
void dump() const {
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 0271a80..aee9d63 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -501,22 +501,20 @@
* when creating/tracking a SkPaint* during defer isn't worth the bother.
*/
struct LayerOp : RecordedOp {
- // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed.
+ // Records a one-use (saveLayer) layer for drawing.
LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
: SUPER_PAINTLESS(LayerOp)
, layerHandle(layerHandle)
, alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
, mode(PaintUtils::getXfermodeDirect(paint))
- , colorFilter(paint ? paint->getColorFilter() : nullptr)
- , destroy(true) {}
+ , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
LayerOp(RenderNode& node)
: RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
, layerHandle(node.getLayerHandle())
, alpha(node.properties().layerProperties().alpha() / 255.0f)
, mode(node.properties().layerProperties().xferMode())
- , colorFilter(node.properties().layerProperties().colorFilter())
- , destroy(false) {}
+ , colorFilter(node.properties().layerProperties().colorFilter()) {}
// Records a handle to the Layer object, since the Layer itself won't be
// constructed until after this operation is constructed.
@@ -527,9 +525,6 @@
// pointer to object owned by either LayerProperties, or a recorded Paint object in a
// BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
SkColorFilter* colorFilter;
-
- // whether to destroy the layer, once rendered
- const bool destroy;
};
}; // namespace uirenderer
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index bb1a044..73b6c02 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -127,7 +127,7 @@
}
void OffscreenBufferPool::clear() {
- for (auto entry : mPool) {
+ for (auto& entry : mPool) {
delete entry.layer;
}
mPool.clear();
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index bcf31ae..0ea246f 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -49,9 +49,12 @@
public:
virtual ~TestRendererBase() {}
virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) {
- ADD_FAILURE() << "Layer creation not expected in this test";
+ ADD_FAILURE() << "Temporary layers not expected in this test";
return nullptr;
}
+ virtual void recycleTemporaryLayer(OffscreenBuffer*) {
+ ADD_FAILURE() << "Temporary layers not expected in this test";
+ }
virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) {
ADD_FAILURE() << "Layer repaint not expected in this test";
}
@@ -710,6 +713,10 @@
EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
EXPECT_TRUE(state.computedState.transform.isIdentity());
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(4, mIndex++);
+ EXPECT_EQ(nullptr, offscreenBuffer);
+ }
};
auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -722,7 +729,7 @@
TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(4, renderer.getIndex());
+ EXPECT_EQ(5, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) {
@@ -774,6 +781,15 @@
EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
} else { ADD_FAILURE(); }
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ const int index = mIndex++;
+ // order isn't important, but we need to see both
+ if (index == 10) {
+ EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer);
+ } else if (index == 11) {
+ EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer);
+ } else { ADD_FAILURE(); }
+ }
};
auto node = TestUtils::createNode(0, 0, 800, 800,
@@ -794,7 +810,7 @@
TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerNestedTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(10, renderer.getIndex());
+ EXPECT_EQ(12, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) {
@@ -1009,10 +1025,15 @@
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(9, mIndex++);
+ EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
}
void endFrame(const Rect& repaintRect) override {
EXPECT_EQ(11, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(12, mIndex++);
+ EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer);
+ }
};
auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping
@@ -1029,7 +1050,7 @@
TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerUnclippedComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(12, renderer.getIndex());
+ EXPECT_EQ(13, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) {
@@ -1151,6 +1172,9 @@
void endFrame(const Rect& repaintRect) override {
EXPECT_EQ(12, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(13, mIndex++);
+ }
};
auto child = TestUtils::createNode(50, 50, 150, 150,
@@ -1188,7 +1212,7 @@
syncedList, sLightGeometry, Caches::getInstance());
HwLayerComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(13, renderer.getIndex());
+ EXPECT_EQ(14, renderer.getIndex());
// clean up layer pointers, so we can safely destruct RenderNodes
*(child->getLayerHandle()) = nullptr;
@@ -1592,6 +1616,9 @@
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(4, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(5, mIndex++);
+ }
};
auto parent = TestUtils::createNode(0, 0, 200, 200,
@@ -1610,7 +1637,7 @@
(FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
ShadowSaveLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(5, renderer.getIndex());
+ EXPECT_EQ(6, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) {
@@ -1839,6 +1866,9 @@
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(4, mIndex++);
+ }
private:
SaveLayerAlphaData* mOutData;
};
@@ -1864,7 +1894,7 @@
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
// assert, since output won't be valid if we haven't seen a save layer triggered
- ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
+ ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
}
RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index 9161f90..e2fc376 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -30,6 +30,25 @@
const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50};
const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+RENDERTHREAD_TEST(LeakCheck, saveLayer_overdrawRejection) {
+ auto node = TestUtils::createNode(0, 0, 100, 100,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(0, 0, 100, 100, 128, SaveFlags::ClipToLayer);
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ canvas.restore();
+
+ // opaque draw, rejects saveLayer beneath
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ });
+ RenderState& renderState = renderThread.renderState();
+ Caches& caches = Caches::getInstance();
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+ TestUtils::createSyncedNodeList(node), sLightGeometery, Caches::getInstance());
+ BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+}
+
RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 37a485e..b7950aa 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -30,119 +30,126 @@
EXPECT_EQ(1024u, OffscreenBuffer::computeIdealDimension(1000));
}
-TEST(OffscreenBuffer, construct) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBuffer layer(thread.renderState(), Caches::getInstance(), 49u, 149u);
- EXPECT_EQ(49u, layer.viewportWidth);
- EXPECT_EQ(149u, layer.viewportHeight);
+RENDERTHREAD_TEST(OffscreenBuffer, construct) {
+ OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 49u, 149u);
+ EXPECT_EQ(49u, layer.viewportWidth);
+ EXPECT_EQ(149u, layer.viewportHeight);
- EXPECT_EQ(64u, layer.texture.width());
- EXPECT_EQ(192u, layer.texture.height());
+ EXPECT_EQ(64u, layer.texture.width());
+ EXPECT_EQ(192u, layer.texture.height());
- EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes());
- });
+ EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes());
}
-TEST(OffscreenBuffer, getTextureCoordinates) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBuffer layerAligned(thread.renderState(), Caches::getInstance(), 256u, 256u);
- EXPECT_EQ(Rect(0, 1, 1, 0),
- layerAligned.getTextureCoordinates());
+RENDERTHREAD_TEST(OffscreenBuffer, getTextureCoordinates) {
+ OffscreenBuffer layerAligned(renderThread.renderState(), Caches::getInstance(), 256u, 256u);
+ EXPECT_EQ(Rect(0, 1, 1, 0),
+ layerAligned.getTextureCoordinates());
- OffscreenBuffer layerUnaligned(thread.renderState(), Caches::getInstance(), 200u, 225u);
- EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
- layerUnaligned.getTextureCoordinates());
- });
+ OffscreenBuffer layerUnaligned(renderThread.renderState(), Caches::getInstance(), 200u, 225u);
+ EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
+ layerUnaligned.getTextureCoordinates());
}
-TEST(OffscreenBuffer, dirty) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBuffer buffer(thread.renderState(), Caches::getInstance(), 256u, 256u);
- buffer.dirty(Rect(-100, -100, 100, 100));
- EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds());
- });
+RENDERTHREAD_TEST(OffscreenBuffer, dirty) {
+ OffscreenBuffer buffer(renderThread.renderState(), Caches::getInstance(), 256u, 256u);
+ buffer.dirty(Rect(-100, -100, 100, 100));
+ EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds());
}
-TEST(OffscreenBufferPool, construct) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
- EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty";
- EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty";
- EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
- << "pool must read size from Properties";
- });
+RENDERTHREAD_TEST(OffscreenBufferPool, construct) {
+ OffscreenBufferPool pool;
+ EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty";
+ EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty";
+ EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
+ << "pool must read size from Properties";
}
-TEST(OffscreenBufferPool, getPutClear) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
+RENDERTHREAD_TEST(OffscreenBufferPool, getPutClear) {
+ OffscreenBufferPool pool;
- auto layer = pool.get(thread.renderState(), 100u, 200u);
- EXPECT_EQ(100u, layer->viewportWidth);
- EXPECT_EQ(200u, layer->viewportHeight);
+ auto layer = pool.get(renderThread.renderState(), 100u, 200u);
+ EXPECT_EQ(100u, layer->viewportWidth);
+ EXPECT_EQ(200u, layer->viewportHeight);
- ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize());
+ ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize());
- pool.putOrDelete(layer);
- ASSERT_EQ(layer->getSizeInBytes(), pool.getSize());
+ pool.putOrDelete(layer);
+ ASSERT_EQ(layer->getSizeInBytes(), pool.getSize());
- auto layer2 = pool.get(thread.renderState(), 102u, 202u);
- EXPECT_EQ(layer, layer2) << "layer should be recycled";
- ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer";
+ auto layer2 = pool.get(renderThread.renderState(), 102u, 202u);
+ EXPECT_EQ(layer, layer2) << "layer should be recycled";
+ ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer";
- pool.putOrDelete(layer);
- EXPECT_EQ(1u, pool.getCount());
- pool.clear();
- EXPECT_EQ(0u, pool.getSize());
- EXPECT_EQ(0u, pool.getCount());
- });
+ pool.putOrDelete(layer);
+ EXPECT_EQ(1u, pool.getCount());
+ pool.clear();
+ EXPECT_EQ(0u, pool.getSize());
+ EXPECT_EQ(0u, pool.getCount());
}
-TEST(OffscreenBufferPool, resize) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
+RENDERTHREAD_TEST(OffscreenBufferPool, resize) {
+ OffscreenBufferPool pool;
- auto layer = pool.get(thread.renderState(), 64u, 64u);
- layer->dirty(Rect(64, 64));
+ auto layer = pool.get(renderThread.renderState(), 64u, 64u);
+ layer->dirty(Rect(64, 64));
- // resize in place
- ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
- EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
- EXPECT_EQ(60u, layer->viewportWidth);
- EXPECT_EQ(55u, layer->viewportHeight);
- EXPECT_EQ(64u, layer->texture.width());
- EXPECT_EQ(64u, layer->texture.height());
+ // resize in place
+ ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
+ EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
+ EXPECT_EQ(60u, layer->viewportWidth);
+ EXPECT_EQ(55u, layer->viewportHeight);
+ EXPECT_EQ(64u, layer->texture.width());
+ EXPECT_EQ(64u, layer->texture.height());
- // resized to use different object in pool
- auto layer2 = pool.get(thread.renderState(), 128u, 128u);
- layer2->dirty(Rect(128, 128));
- EXPECT_FALSE(layer2->region.isEmpty());
- pool.putOrDelete(layer2);
- ASSERT_EQ(1u, pool.getCount());
+ // resized to use different object in pool
+ auto layer2 = pool.get(renderThread.renderState(), 128u, 128u);
+ layer2->dirty(Rect(128, 128));
+ EXPECT_FALSE(layer2->region.isEmpty());
+ pool.putOrDelete(layer2);
+ ASSERT_EQ(1u, pool.getCount());
- ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
- EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
- EXPECT_EQ(120u, layer2->viewportWidth);
- EXPECT_EQ(125u, layer2->viewportHeight);
- EXPECT_EQ(128u, layer2->texture.width());
- EXPECT_EQ(128u, layer2->texture.height());
+ ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
+ EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
+ EXPECT_EQ(120u, layer2->viewportWidth);
+ EXPECT_EQ(125u, layer2->viewportHeight);
+ EXPECT_EQ(128u, layer2->texture.width());
+ EXPECT_EQ(128u, layer2->texture.height());
- // original allocation now only thing in pool
- EXPECT_EQ(1u, pool.getCount());
- EXPECT_EQ(layer->getSizeInBytes(), pool.getSize());
+ // original allocation now only thing in pool
+ EXPECT_EQ(1u, pool.getCount());
+ EXPECT_EQ(layer->getSizeInBytes(), pool.getSize());
- pool.putOrDelete(layer2);
- });
+ pool.putOrDelete(layer2);
}
-TEST(OffscreenBufferPool, putAndDestroy) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
- // layer too big to return to the pool
- // Note: this relies on the fact that the pool won't reject based on max texture size
- auto hugeLayer = pool.get(thread.renderState(), pool.getMaxSize() / 64, 64);
- EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
- pool.putOrDelete(hugeLayer);
- EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
- });
+RENDERTHREAD_TEST(OffscreenBufferPool, putAndDestroy) {
+ OffscreenBufferPool pool;
+ // layer too big to return to the pool
+ // Note: this relies on the fact that the pool won't reject based on max texture size
+ auto hugeLayer = pool.get(renderThread.renderState(), pool.getMaxSize() / 64, 64);
+ EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
+ pool.putOrDelete(hugeLayer);
+ EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
+}
+
+RENDERTHREAD_TEST(OffscreenBufferPool, clear) {
+ EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
+ OffscreenBufferPool pool;
+
+ // Create many buffers, with several at each size
+ std::vector<OffscreenBuffer*> buffers;
+ for (int size = 32; size <= 128; size += 32) {
+ for (int i = 0; i < 10; i++) {
+ buffers.push_back(pool.get(renderThread.renderState(), size, size));
+ }
+ }
+ EXPECT_EQ(0u, pool.getCount()) << "Expect nothing inside";
+ for (auto& buffer : buffers) pool.putOrDelete(buffer);
+ EXPECT_EQ(40u, pool.getCount()) << "Expect all items added";
+ EXPECT_EQ(40, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
+ pool.clear();
+ EXPECT_EQ(0u, pool.getCount()) << "Expect all items cleared";
+
+ EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
}
diff --git a/media/java/android/media/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
index c2cc2b9..d5115de 100644
--- a/media/java/android/media/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -28,7 +28,8 @@
void closeDevice();
// connects the input port pfd to the specified output port
- void connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
+ // Returns the PID of the called process.
+ int connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
MidiDeviceInfo getDeviceInfo();
void setDeviceInfo(in MidiDeviceInfo deviceInfo);
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index e1990cd..e4588fe 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -19,6 +19,7 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -181,9 +182,16 @@
}
try {
IBinder token = new Binder();
- mDeviceServer.connectPorts(token, pfd, outputPortNumber);
- // close our copy of the file descriptor
- IoUtils.closeQuietly(pfd);
+ int calleePid = mDeviceServer.connectPorts(token, pfd, outputPortNumber);
+ // If the service is a different Process then it will duplicate the pfd
+ // and we can safely close this one.
+ // But if the service is in the same Process then closing the pfd will
+ // kill the connection. So don't do that.
+ if (calleePid != Process.myPid()) {
+ // close our copy of the file descriptor
+ IoUtils.closeQuietly(pfd);
+ }
+
return new MidiConnection(token, inputPort);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in connectPorts");
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 19ff624..f0abf71 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -254,7 +254,7 @@
}
@Override
- public void connectPorts(IBinder token, ParcelFileDescriptor pfd,
+ public int connectPorts(IBinder token, ParcelFileDescriptor pfd,
int outputPortNumber) {
MidiInputPort inputPort = new MidiInputPort(pfd, outputPortNumber);
MidiDispatcher dispatcher = mOutputPortDispatchers[outputPortNumber];
@@ -270,6 +270,7 @@
synchronized (mPortClients) {
mPortClients.put(token, client);
}
+ return Process.myPid(); // for caller to detect same process ID
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 9005442..5ea6cfa 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -69,7 +69,7 @@
final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
mRoots = new RootsCache(this);
- mRoots.updateAsync();
+ mRoots.updateAsync(false);
mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
@@ -105,7 +105,7 @@
final String packageName = data.getSchemeSpecificPart();
mRoots.updatePackageAsync(packageName);
} else {
- mRoots.updateAsync();
+ mRoots.updateAsync(true);
}
}
};
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 09fadc9..594e02f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -122,7 +122,7 @@
/**
* Gather roots from all known storage providers.
*/
- public void updateAsync() {
+ public void updateAsync(boolean forceRefreshAll) {
// NOTE: This method is called when the UI language changes.
// For that reason we update our RecentsRoot to reflect
@@ -139,14 +139,15 @@
| Root.FLAG_SUPPORTS_CREATE));
assert(mRecentsRoot.availableBytes == -1);
- new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new UpdateTask(forceRefreshAll, null)
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
* Gather roots from storage providers belonging to given package name.
*/
public void updatePackageAsync(String packageName) {
- new UpdateTask(packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new UpdateTask(false, packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
@@ -223,23 +224,22 @@
}
private class UpdateTask extends AsyncTask<Void, Void, Void> {
+ private final boolean mForceRefreshAll;
private final String mForceRefreshPackage;
private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
private final HashSet<String> mTaskStoppedAuthorities = new HashSet<>();
/**
- * Update all roots.
+ * Create task to update roots cache.
+ *
+ * @param forceRefreshAll when true, all previously cached values for
+ * all packages should be ignored.
+ * @param forceRefreshPackage when non-null, all previously cached
+ * values for this specific package should be ignored.
*/
- public UpdateTask() {
- this(null);
- }
-
- /**
- * Force update roots belonging to given package name. Other roots will
- * be copied from cached {@link #mRoots} values.
- */
- public UpdateTask(String forceRefreshPackage) {
+ public UpdateTask(boolean forceRefreshAll, String forceRefreshPackage) {
+ mForceRefreshAll = forceRefreshAll;
mForceRefreshPackage = forceRefreshPackage;
}
@@ -247,14 +247,6 @@
protected Void doInBackground(Void... params) {
final long start = SystemClock.elapsedRealtime();
- if (mForceRefreshPackage != null) {
- // We must have previously cached values to fill in non-matching
- // packages, so wait around for successful first load.
- if (!waitForFirstLoad()) {
- return null;
- }
- }
-
mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot);
final ContentResolver resolver = mContext.getContentResolver();
@@ -300,7 +292,8 @@
return;
}
- final boolean forceRefresh = Objects.equals(mForceRefreshPackage, info.packageName);
+ final boolean forceRefresh = mForceRefreshAll
+ || Objects.equals(info.packageName, mForceRefreshPackage);
mTaskRoots.putAll(info.authority, loadRootsForAuthority(mContext.getContentResolver(),
info.authority, forceRefresh));
}
diff --git a/packages/PrintServiceRecommendationService/res/values/strings.xml b/packages/PrintServiceRecommendationService/res/values/strings.xml
index 83d3800..07d0004 100644
--- a/packages/PrintServiceRecommendationService/res/values/strings.xml
+++ b/packages/PrintServiceRecommendationService/res/values/strings.xml
@@ -23,7 +23,7 @@
<string name="plugin_vendor_brother">Brother</string>
<string name="plugin_vendor_canon">Canon</string>
<string name="plugin_vendor_xerox">Xerox</string>
- <string name="plugin_vendor_samsung">Samsung Electorics</string>
+ <string name="plugin_vendor_samsung">Samsung Electronics</string>
<string name="plugin_vendor_epson">Epson</string>
<string name="plugin_vendor_konika_minolta">Konika Minolta</string>
<string name="plugin_vendor_fuji">Fuji</string>
diff --git a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
index fda2768..119943c 100644
--- a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
+++ b/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
@@ -46,7 +46,7 @@
<vendor>
<name>@string/plugin_vendor_canon</name>
- <package>com.xerox.printservice</package>
+ <package>jp.co.canon.android.printservice.plugin</package>
<mdns-names>
<mdns-name>Canon</mdns-name>
</mdns-names>
@@ -54,7 +54,7 @@
<vendor>
<name>@string/plugin_vendor_xerox</name>
- <package>jp.co.canon.android.printservice.plugin</package>
+ <package>com.xerox.printservice</package>
<mdns-names>
<mdns-name>Xerox</mdns-name>
</mdns-names>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index aa95be2..d7c9eab 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -144,7 +144,9 @@
return true;
}
}
- mService.disconnect(device);
+ for (BluetoothDevice src : srcs) {
+ mService.disconnect(device);
+ }
}
Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index aa3f6e5..d12ab29 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -514,7 +514,7 @@
if (canBeExpanded) {
if (DEBUG) Log.d(TAG, "working on an expandable child");
mNaturalHeight = mScaler.getNaturalHeight();
- mSmallSize = v.getMinExpandHeight();
+ mSmallSize = v.getCollapsedHeight();
} else {
if (DEBUG) Log.d(TAG, "working on a non-expandable child");
mNaturalHeight = mOldHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index e0d0486..ef81f9e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -367,8 +367,10 @@
int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
int childWidth = mEmptyView.getMeasuredWidth();
int childHeight = mEmptyView.getMeasuredHeight();
- int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
- int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
+ int childLeft = left + mSystemInsets.left +
+ Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
+ int childTop = top + mSystemInsets.top +
+ Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 601d910..3005535 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -240,16 +240,6 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
- getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-
- @Override
- public void onGlobalLayout() {
- getViewTreeObserver().removeOnGlobalLayoutListener(this);
- mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
- mHandle.getLeft() + mHandle.getWidth(),
- mHandle.getTop() + mHandle.getHeight()));
- }
- });
}
@Override
@@ -274,6 +264,15 @@
return super.onApplyWindowInsets(insets);
}
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
+ mHandle.getRight(), mHandle.getBottom()));
+ }
+ }
+
public void setWindowManager(DividerWindowManager windowManager) {
mWindowManager = windowManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 4ed6426..8102fae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -107,7 +107,6 @@
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.GearDisplayedListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import java.util.ArrayList;
@@ -120,7 +119,7 @@
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
- ExpandableNotificationRow.OnExpandClickListener, GearDisplayedListener {
+ ExpandableNotificationRow.OnExpandClickListener {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
@@ -242,7 +241,6 @@
// which notification is currently being longpress-examined by the user
private NotificationGuts mNotificationGutsExposed;
- private ExpandableNotificationRow mNotificationGearDisplayed;
private KeyboardShortcuts mKeyboardShortcuts;
@@ -1067,10 +1065,6 @@
guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
}
- protected GearDisplayedListener getGearDisplayedListener() {
- return this;
- }
-
protected SwipeHelper.LongPressListener getNotificationLongClicker() {
return new SwipeHelper.LongPressListener() {
@Override
@@ -1106,7 +1100,8 @@
// Post to ensure the the guts are properly laid out.
guts.post(new Runnable() {
public void run() {
- dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
+ dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
+ false /* animate */);
guts.setVisibility(View.VISIBLE);
final double horz = Math.max(guts.getWidth() - x, x);
final double vert = Math.max(guts.getHeight() - y, y);
@@ -1135,22 +1130,22 @@
};
}
- @Override
- public void onGearDisplayed(ExpandableNotificationRow row) {
- MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
- row.getStatusBarNotification().getPackageName());
- mNotificationGearDisplayed = row;
+ /**
+ * Returns the exposed NotificationGuts or null if none are exposed.
+ */
+ public NotificationGuts getExposedGuts() {
+ return mNotificationGutsExposed;
}
public void dismissPopups() {
- dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
+ dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
}
private void dismissPopups(int x, int y) {
- dismissPopups(x, y, true /* resetGear */);
+ dismissPopups(x, y, true /* resetGear */, false /* animate */);
}
- public void dismissPopups(int x, int y, boolean resetGear) {
+ public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
if (mNotificationGutsExposed != null) {
final NotificationGuts v = mNotificationGutsExposed;
mNotificationGutsExposed = null;
@@ -1178,9 +1173,8 @@
v.setExposed(false);
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
}
- if (resetGear && mNotificationGearDisplayed != null) {
- mNotificationGearDisplayed.resetTranslation();
- mNotificationGearDisplayed = null;
+ if (resetGear) {
+ mStackScroller.resetExposedGearView(animate, true /* force */);
}
}
@@ -1843,11 +1837,12 @@
.getIdentifier();
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
&& mKeyguardManager.isDeviceLocked(userId)) {
- // Show work challenge, do not run pendingintent and
- // remove notification
- startWorkChallenge(userId, intent.getIntentSender(),
- notificationKey);
- return;
+ if (startWorkChallengeIfNecessary(userId,
+ intent.getIntentSender(), notificationKey)) {
+ // Show work challenge, do not run pendingintent and
+ // remove notification
+ return;
+ }
}
}
try {
@@ -1885,21 +1880,25 @@
}, afterKeyguardGone);
}
- public void startWorkChallenge(int userId, IntentSender intendSender,
+ public boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
+ final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+ null, userId);
+ if (newIntent == null) {
+ return false;
+ }
final Intent callBackIntent = new Intent(
WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
callBackIntent.setPackage(mContext.getPackageName());
- final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
- null, userId);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_CLEAR_TASK);
newIntent.putExtra(Intent.EXTRA_INTENT, PendingIntent
.getBroadcast(mContext, 0, callBackIntent, 0).getIntentSender());
mContext.startActivity(newIntent);
+ return true;
}
public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 7f87c3c..2dabf5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -170,22 +170,22 @@
: RUBBERBAND_FACTOR_STATIC;
float rubberband = heightDelta * rubberbandFactor;
if (expandable
- && (rubberband + child.getMinExpandHeight()) > child.getMaxContentHeight()) {
+ && (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
float overshoot =
- (rubberband + child.getMinExpandHeight()) - child.getMaxContentHeight();
+ (rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
rubberband -= overshoot;
}
- child.setActualHeight((int) (child.getMinExpandHeight() + rubberband));
+ child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
}
private void cancelExpansion(final ExpandableView child) {
- if (child.getActualHeight() == child.getMinExpandHeight()) {
+ if (child.getActualHeight() == child.getCollapsedHeight()) {
mCallback.setUserLockedChild(child, false);
return;
}
ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
- child.getActualHeight(), child.getMinExpandHeight());
+ child.getActualHeight(), child.getCollapsedHeight());
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f9edeb3..7ca7d12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -470,7 +470,7 @@
if(mExpandedWhenPinned) {
return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
} else if (atLeastMinHeight) {
- return Math.max(getMinHeight(), mHeadsUpHeight);
+ return Math.max(getCollapsedHeight(), mHeadsUpHeight);
} else {
return mHeadsUpHeight;
}
@@ -1040,12 +1040,12 @@
} else if (isExpanded()) {
return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
} else {
- return Math.max(getMinHeight(), mHeadsUpHeight);
+ return Math.max(getCollapsedHeight(), mHeadsUpHeight);
}
} else if (isExpanded()) {
return getMaxExpandHeight();
} else {
- return getMinHeight();
+ return getCollapsedHeight();
}
}
@@ -1301,9 +1301,9 @@
}
@Override
- public int getMinExpandHeight() {
+ public int getCollapsedHeight() {
if (mIsSummaryWithChildren && !mShowingPublic) {
- return mChildrenContainer.getMinExpandHeight();
+ return mChildrenContainer.getCollapsedHeight();
}
return getMinHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 91418ad..6dcd61f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -153,11 +153,11 @@
}
/**
- * @return The minimum height this child chan be expanded to. Note that this might be different
- * than {@link #getMinHeight()} because some elements can't be collapsed by an expand gesture
- * to it's absolute minimal height
+ * @return The collapsed height of this view. Note that this might be different
+ * than {@link #getMinHeight()} because some elements like groups may have different sizes when
+ * they are system expanded.
*/
- public int getMinExpandHeight() {
+ public int getCollapsedHeight() {
return getHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index f4fb0b9..5b00523 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -604,7 +604,7 @@
}
int expandedVisualType = getVisualTypeForHeight(height);
int collapsedVisualType = getVisualTypeForHeight(
- mContainingNotification.getMinExpandHeight());
+ mContainingNotification.getCollapsedHeight());
return mTransformationStartVisibleType == collapsedVisualType
? expandedVisualType
: collapsedVisualType;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index 88aafe0..a5ebbba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -41,7 +41,7 @@
/**
* Called when a notification is slid back over the gear.
*/
- public void onSettingsIconRowReset(NotificationSettingsIconRow row);
+ public void onSettingsIconRowReset(ExpandableNotificationRow row);
}
private ExpandableNotificationRow mParent;
@@ -94,7 +94,7 @@
mDismissing = false;
setIconLocation(true /* on left */, true /* force */);
if (mListener != null) {
- mListener.onSettingsIconRowReset(this);
+ mListener.onSettingsIconRowReset(mParent);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c563eb6..fce893e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -755,7 +755,6 @@
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
- mStackScroller.setGearDisplayedListener(getGearDisplayedListener());
mStackScroller.setPhoneStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setHeadsUpManager(mHeadsUpManager);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 6a2ecf4e..ebfa018 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -226,6 +226,10 @@
return false;
}
}
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mStackScrollLayout.closeControlsIfOutsideTouch(ev);
+ }
+
return super.dispatchTouchEvent(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index dc567fc..2f4e799 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -592,7 +592,7 @@
public float getGroupExpandFraction() {
int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight();
- int minExpandHeight = getMinExpandHeight();
+ int minExpandHeight = getCollapsedHeight();
float factor = (mActualHeight - minExpandHeight)
/ (float) (visibleChildrenExpandedHeight - minExpandHeight);
return Math.max(0.0f, Math.min(1.0f, factor));
@@ -618,11 +618,14 @@
}
public int getMinHeight() {
- return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+ return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
}
- public int getMinExpandHeight() {
- int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+ public int getCollapsedHeight() {
+ return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+ }
+
+ private int getMinHeight(int maxAllowedVisibleChildren) {
int minExpandHeight = mNotificationHeaderHeight;
int visibleChildren = 0;
boolean firstChild = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4a8abe6..46a49ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -60,6 +60,7 @@
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationGuts;
import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.NotificationSettingsIconRow;
import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
@@ -220,7 +221,6 @@
*/
private int mMaxScrollAfterExpand;
private SwipeHelper.LongPressListener mLongPressListener;
- private GearDisplayedListener mGearDisplayedListener;
private NotificationSettingsIconRow mCurrIconRow;
private View mTranslatingParentView;
@@ -374,8 +374,12 @@
}
@Override
- public void onSettingsIconRowReset(NotificationSettingsIconRow row) {
- mSwipeHelper.setSnappedToGear(false);
+ public void onSettingsIconRowReset(ExpandableNotificationRow row) {
+ if (mTranslatingParentView != null && row == mTranslatingParentView) {
+ mSwipeHelper.setSnappedToGear(false);
+ mGearExposedView = null;
+ mTranslatingParentView = null;
+ }
}
@Override
@@ -669,10 +673,6 @@
mLongPressListener = listener;
}
- public void setGearDisplayedListener(GearDisplayedListener listener) {
- mGearDisplayedListener = listener;
- }
-
public void setQsContainer(ViewGroup qsContainer) {
mQsContainer = qsContainer;
}
@@ -737,17 +737,9 @@
// We start the swipe and snap back in the same frame, we don't want any animation
mDragAnimPendingChildren.remove(animView);
}
-
- if (mCurrIconRow != null) {
- if (targetLeft == 0) {
- mCurrIconRow.resetState();
- mCurrIconRow = null;
- if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
- mGearExposedView = null;
- }
- } else {
- mSwipeHelper.setSnappedToGear(true);
- }
+ if (mCurrIconRow != null && targetLeft == 0) {
+ mCurrIconRow.resetState();
+ mCurrIconRow = null;
}
}
@@ -1947,7 +1939,7 @@
public int getPeekHeight() {
final ExpandableView firstChild = getFirstChildNotGone();
- final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
+ final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
: mCollapsedSize;
return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
+ mBottomStackSlowDownHeight;
@@ -3470,13 +3462,6 @@
public void flingTopOverscroll(float velocity, boolean open);
}
- /**
- * A listener that is notified when the gear is shown behind a notification.
- */
- public interface GearDisplayedListener {
- void onGearDisplayed(ExpandableNotificationRow row);
- }
-
private class NotificationSwipeHelper extends SwipeHelper {
private static final long GEAR_SHOW_DELAY = 60;
private CheckForDrag mCheckForDrag;
@@ -3503,7 +3488,7 @@
mCurrIconRow = null;
// Slide back any notifications that might be showing a gear
- resetExposedGearView();
+ resetExposedGearView(true /* animate */, false /* force */);
if (currView instanceof ExpandableNotificationRow) {
// Set the listener for the current row's gear
@@ -3551,8 +3536,7 @@
public void dismissChild(final View view, float velocity,
boolean useAccelerateInterpolator) {
super.dismissChild(view, velocity, useAccelerateInterpolator);
- cancelCheckForDrag();
- setSnappedToGear(false);
+ handleGearCoveredOrDismissed();
}
@Override
@@ -3560,11 +3544,17 @@
super.snapChild(animView, targetLeft, velocity);
onDragCancelled(animView);
if (targetLeft == 0) {
- cancelCheckForDrag();
- setSnappedToGear(false);
+ handleGearCoveredOrDismissed();
}
}
+ private void handleGearCoveredOrDismissed() {
+ cancelCheckForDrag();
+ setSnappedToGear(false);
+ if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
+ mGearExposedView = null;
+ }
+ }
@Override
public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
@@ -3624,9 +3614,10 @@
final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
: -snapBackThreshold;
mGearExposedView = mTranslatingParentView;
- if (mGearDisplayedListener != null
- && (animView instanceof ExpandableNotificationRow)) {
- mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
+ if (animView instanceof ExpandableNotificationRow) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+ ((ExpandableNotificationRow) animView).getStatusBarNotification()
+ .getPackageName());
}
if (mCurrIconRow != null) {
mCurrIconRow.setSnapping(true);
@@ -3637,6 +3628,9 @@
}
private boolean swipedEnoughToShowGear(View animView) {
+ if (mTranslatingParentView == null) {
+ return false;
+ }
final float snapBackThreshold = getSpaceForGear(animView);
final float translation = getTranslation(animView);
final boolean fromLeft = translation > 0;
@@ -3682,6 +3676,37 @@
}
}
+ public void closeControlsIfOutsideTouch(MotionEvent ev) {
+ NotificationGuts guts = mPhoneStatusBar.getExposedGuts();
+ View view = null;
+ int height = 0;
+ if (guts != null) {
+ // Checking guts
+ view = guts;
+ height = guts.getActualHeight();
+ } else if (mCurrIconRow != null && mCurrIconRow.isVisible()
+ && mTranslatingParentView != null) {
+ // Checking gear
+ view = mTranslatingParentView;
+ height = ((ExpandableView) mTranslatingParentView).getActualHeight();
+ }
+ if (view != null) {
+ final int rx = (int) ev.getRawX();
+ final int ry = (int) ev.getRawY();
+
+ getLocationOnScreen(mTempInt2);
+ int[] location = new int[2];
+ view.getLocationOnScreen(location);
+ final int x = location[0] - mTempInt2[0];
+ final int y = location[1] - mTempInt2[1];
+ Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
+ if (!rect.contains((int) rx, (int) ry)) {
+ // Touch was outside visible guts / gear notification, close what's visible
+ mPhoneStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
+ }
+ }
+ }
+
/**
* Returns whether the gesture is towards the gear location or not.
*/
@@ -3729,6 +3754,9 @@
private final class CheckForDrag implements Runnable {
@Override
public void run() {
+ if (mTranslatingParentView == null) {
+ return;
+ }
final float translation = getTranslation(mTranslatingParentView);
final float absTransX = Math.abs(translation);
final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
@@ -3744,20 +3772,24 @@
}
}
- private void resetExposedGearView() {
- if (mGearExposedView == null || mGearExposedView == mTranslatingParentView) {
+ public void resetExposedGearView(boolean animate, boolean force) {
+ if (mGearExposedView == null
+ || (!force && mGearExposedView == mTranslatingParentView)) {
// If no gear is showing or it's showing for this view we do nothing.
return;
}
-
final View prevGearExposedView = mGearExposedView;
+ if (animate) {
+ Animator anim = getViewTranslationAnimator(prevGearExposedView,
+ 0 /* leftTarget */, null /* updateListener */);
+ if (anim != null) {
+ anim.start();
+ }
+ } else if (mGearExposedView instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) mGearExposedView).resetTranslation();
+ }
mGearExposedView = null;
mGearSnappedTo = false;
- Animator anim = getViewTranslationAnimator(prevGearExposedView,
- 0 /* leftTarget */, null /* updateListener */);
- if (anim != null) {
- anim.start();
- }
}
}
@@ -3773,6 +3805,14 @@
}
}
+ public void resetExposedGearView(boolean animate, boolean force) {
+ mSwipeHelper.resetExposedGearView(animate, force);
+ }
+
+ public void closeControlsIfOutsideTouch(MotionEvent ev) {
+ mSwipeHelper.closeControlsIfOutsideTouch(ev);
+ }
+
static class AnimationEvent {
static AnimationFilter[] FILTERS = new AnimationFilter[] {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 4c94fe9..c7333c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -368,7 +368,7 @@
childViewState.location = StackViewState.LOCATION_UNKNOWN;
paddingAfterChild = getPaddingAfterChild(algorithmState, child);
int childHeight = getMaxAllowedChildHeight(child);
- int minHeight = child.getMinHeight();
+ int collapsedHeight = child.getCollapsedHeight();
childViewState.yTranslation = currentYPosition;
if (i == 0) {
updateFirstChildHeight(child, childViewState, childHeight, ambientState);
@@ -384,7 +384,7 @@
// According to the regular scroll view we are fully translated out of the
// bottom of the screen so we are fully in the bottom stack
updateStateForChildFullyInBottomStack(algorithmState,
- bottomStackStart, childViewState, minHeight, ambientState, child);
+ bottomStackStart, childViewState, collapsedHeight, ambientState, child);
} else {
// According to the regular scroll view we are currently translating out of /
// into the bottom of the screen
@@ -475,17 +475,17 @@
float newTranslation = Math.max(ambientState.getTopPadding()
+ ambientState.getStackTranslation(), childState.yTranslation);
childState.height = (int) Math.max(childState.height - (newTranslation
- - childState.yTranslation), row.getMinHeight());
+ - childState.yTranslation), row.getCollapsedHeight());
childState.yTranslation = newTranslation;
}
private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
StackViewState childState) {
float newTranslation;
- float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getMinHeight();
+ float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getCollapsedHeight();
newTranslation = Math.min(childState.yTranslation, bottomPosition);
childState.height = (int) Math.max(childState.height
- - (childState.yTranslation - newTranslation), row.getMinHeight());
+ - (childState.yTranslation - newTranslation), row.getCollapsedHeight());
childState.yTranslation = newTranslation;
}
@@ -534,10 +534,10 @@
float offset = mBottomStackIndentationFunctor.getValue(algorithmState.partialInBottom);
algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
int newHeight = childHeight;
- if (childHeight > child.getMinHeight()) {
+ if (childHeight > child.getCollapsedHeight()) {
newHeight = (int) Math.max(Math.min(transitioningPositionStart + offset -
getPaddingAfterChild(algorithmState, child) - currentYPosition, childHeight),
- child.getMinHeight());
+ child.getCollapsedHeight());
childViewState.height = newHeight;
}
childViewState.yTranslation = transitioningPositionStart + offset - newHeight
@@ -547,7 +547,7 @@
private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
float transitioningPositionStart, StackViewState childViewState,
- int minHeight, AmbientState ambientState, ExpandableView child) {
+ int collapsedHeight, AmbientState ambientState, ExpandableView child) {
float currentYPosition;
algorithmState.itemsInBottomStack += 1.0f;
if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
@@ -568,16 +568,14 @@
childViewState.location = StackViewState.LOCATION_BOTTOM_STACK_HIDDEN;
currentYPosition = ambientState.getInnerHeight();
}
- childViewState.height = minHeight;
- childViewState.yTranslation = currentYPosition - minHeight;
+ childViewState.height = collapsedHeight;
+ childViewState.yTranslation = currentYPosition - collapsedHeight;
}
/**
* Update the height of the first child i.e clamp it to the bottom stack
*
- *
-
* @param child the child to update
* @param childViewState the viewstate of the child
* @param childHeight the height of the child
@@ -591,7 +589,7 @@
mBottomStackSlowDownLength + ambientState.getScrollY();
// Collapse and expand the first child while the shade is being expanded
childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
- child.getMinHeight());
+ child.getCollapsedHeight());
}
/**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b6a99c8..1b0d3ac 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -744,8 +744,8 @@
}
@Override
- public int[] startListening(IAppWidgetHost callbacks, String callingPackage,
- int hostId, List<RemoteViews> updatedViews) {
+ public ParceledListSlice<RemoteViews> startListening(IAppWidgetHost callbacks,
+ String callingPackage, int hostId, int[] appWidgetIds, int[] updatedIds) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -762,21 +762,21 @@
// sure the caller can only access hosts it owns.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupOrAddHostLocked(id);
-
host.callbacks = callbacks;
- updatedViews.clear();
-
- ArrayList<Widget> instances = host.widgets;
- int N = instances.size();
- int[] updatedIds = new int[N];
+ int N = appWidgetIds.length;
+ ArrayList<RemoteViews> outViews = new ArrayList<>(N);
+ RemoteViews rv;
+ int added = 0;
for (int i = 0; i < N; i++) {
- Widget widget = instances.get(i);
- updatedIds[i] = widget.appWidgetId;
- updatedViews.add(cloneIfLocalBinder(widget.getEffectiveViewsLocked()));
+ rv = host.getPendingViewsForId(appWidgetIds[i]);
+ if (rv != null) {
+ updatedIds[added] = appWidgetIds[i];
+ outViews.add(rv);
+ added++;
+ }
}
-
- return updatedIds;
+ return new ParceledListSlice<>(outViews);
}
}
@@ -1884,6 +1884,10 @@
}
private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
+ long requestTime = SystemClock.uptimeMillis();
+ if (widget != null) {
+ widget.lastUpdateTime = requestTime;
+ }
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
return;
@@ -1893,6 +1897,7 @@
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.arg3 = updateViews;
+ args.arg4 = requestTime;
args.argi1 = widget.appWidgetId;
mCallbackHandler.obtainMessage(
@@ -1901,9 +1906,10 @@
}
private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
- int appWidgetId, RemoteViews views) {
+ int appWidgetId, RemoteViews views, long requestTime) {
try {
callbacks.updateAppWidget(appWidgetId, views);
+ host.lastWidgetUpdateTime = requestTime;
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3400,10 +3406,11 @@
Host host = (Host) args.arg1;
IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
RemoteViews views = (RemoteViews) args.arg3;
+ long requestTime = (Long) args.arg4;
final int appWidgetId = args.argi1;
args.recycle();
- handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views);
+ handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views, requestTime);
} break;
case MSG_NOTIFY_PROVIDER_CHANGED: {
@@ -3771,6 +3778,7 @@
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
int tag = TAG_UNDEFINED; // for use while saving state (the index)
+ long lastWidgetUpdateTime; // last time we were successfully able to send an update.
public int getUserId() {
return UserHandle.getUserId(id.uid);
@@ -3792,6 +3800,23 @@
return false;
}
+ /**
+ * Returns the RemoveViews for the provided widget id if an update is pending
+ * for that widget.
+ */
+ public RemoteViews getPendingViewsForId(int appWidgetId) {
+ long updateTime = lastWidgetUpdateTime;
+ int N = widgets.size();
+ for (int i = 0; i < N; i++) {
+ Widget widget = widgets.get(i);
+ if (widget.appWidgetId == appWidgetId
+ && widget.lastUpdateTime > updateTime) {
+ return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
+ }
+ }
+ return null;
+ }
+
@Override
public String toString() {
return "Host{" + id + (zombie ? " Z" : "") + '}';
@@ -3862,6 +3887,7 @@
RemoteViews maskedViews;
Bundle options;
Host host;
+ long lastUpdateTime;
@Override
public String toString() {
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index c38a89e..377a9e2 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1046,7 +1046,9 @@
op.duration = 0;
final int switchCode = AppOpsManager.opToSwitch(code);
UidState uidState = ops.uidState;
- if (uidState.opModes != null) {
+ // If there is a non-default per UID policy (we set UID op mode only if
+ // non-default) it takes over, otherwise use the per package policy.
+ if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
final int uidMode = uidState.opModes.get(switchCode);
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
@@ -1055,13 +1057,15 @@
op.rejectTime = System.currentTimeMillis();
return uidMode;
}
- }
- final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
- op.rejectTime = System.currentTimeMillis();
- return switchOp.mode;
+ } else {
+ final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+ if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+ + switchCode + " (" + code + ") uid " + uid + " package "
+ + packageName);
+ op.rejectTime = System.currentTimeMillis();
+ return switchOp.mode;
+ }
}
if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+ " package " + packageName);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a4d6be5..82a36b4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4134,8 +4134,8 @@
// }
updateTcpBufferSizes(networkAgent);
- final boolean flushDns = updateRoutes(newLp, oldLp, netId);
- updateDnses(newLp, oldLp, netId, flushDns);
+ updateRoutes(newLp, oldLp, netId);
+ updateDnses(newLp, oldLp, netId);
updateClat(newLp, oldLp, networkAgent);
if (isDefaultNetwork(networkAgent)) {
@@ -4238,30 +4238,24 @@
return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
}
- private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
- boolean flush) {
- if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
- Collection<InetAddress> dnses = newLp.getDnsServers();
- if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
- try {
- mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses),
- newLp.getDomains());
- } catch (Exception e) {
- loge("Exception in setDnsServersForNetwork: " + e);
- }
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
- flushVmDnsCache();
- } else if (flush) {
- try {
- mNetd.flushNetworkDnsCache(netId);
- } catch (Exception e) {
- loge("Exception in flushNetworkDnsCache: " + e);
- }
- flushVmDnsCache();
+ private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
+ if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
+ return; // no updating necessary
}
+
+ Collection<InetAddress> dnses = newLp.getDnsServers();
+ if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
+ try {
+ mNetd.setDnsServersForNetwork(
+ netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
+ } catch (Exception e) {
+ loge("Exception in setDnsServersForNetwork: " + e);
+ }
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ if (defaultNai != null && defaultNai.network.netId == netId) {
+ setDefaultDnsSystemProperties(dnses);
+ }
+ flushVmDnsCache();
}
private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index c6d536d..bf4df94 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1937,16 +1937,6 @@
}
@Override
- public void flushNetworkDnsCache(int netId) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- try {
- mConnector.execute("resolver", "flushnet", netId);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
- }
-
- @Override
public void setFirewallEnabled(boolean enabled) {
enforceSystemUid();
try {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 879bb6f..2a78f90 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -18,10 +18,12 @@
import android.Manifest.permission;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
@@ -30,6 +32,7 @@
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.ScoredNetwork;
import android.os.Binder;
+import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -55,17 +58,17 @@
*/
public class NetworkScoreService extends INetworkScoreService.Stub {
private static final String TAG = "NetworkScoreService";
+ private static final boolean DBG = false;
private final Context mContext;
-
private final Map<Integer, INetworkScoreCache> mScoreCaches;
-
/** Lock used to update mReceiver when scorer package changes occur. */
- private Object mReceiverLock = new Object[0];
+ private final Object mReceiverLock = new Object[0];
/** Clears scores when the active scorer package is no longer valid. */
@GuardedBy("mReceiverLock")
private ScorerChangedReceiver mReceiver;
+ private ScoringServiceConnection mServiceConnection;
private class ScorerChangedReceiver extends BroadcastReceiver {
final String mRegisteredPackage;
@@ -77,14 +80,23 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if ((Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
- Intent.ACTION_PACKAGE_REPLACED.equals(action) ||
- Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) &&
- NetworkScorerAppManager.getActiveScorer(mContext) == null) {
- // Package change has invalidated a scorer.
- Log.i(TAG, "Package " + mRegisteredPackage +
- " is no longer valid, disabling scoring");
- setScorerInternal(null);
+ if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+ || Intent.ACTION_PACKAGE_REPLACED.equals(action)
+ || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+ NetworkScorerAppData activeScorer =
+ NetworkScorerAppManager.getActiveScorer(mContext);
+ if (activeScorer == null) {
+ // Package change has invalidated a scorer.
+ Log.i(TAG, "Package " + mRegisteredPackage +
+ " is no longer valid, disabling scoring.");
+ setScorerInternal(null);
+ } else if (activeScorer.mScoringServiceClassName == null) {
+ // The scoring service is not available, make sure it's unbound.
+ unbindFromScoringServiceIfNeeded();
+ } else {
+ // The scoring service may have changed or been added.
+ bindToScoringServiceIfNeeded(activeScorer);
+ }
}
}
}
@@ -96,6 +108,7 @@
/** Called when the system is ready to run third-party code but before it actually does so. */
void systemReady() {
+ if (DBG) Log.d(TAG, "systemReady");
ContentResolver cr = mContext.getContentResolver();
if (Settings.Global.getInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 0) == 0) {
// On first run, we try to initialize the scorer to the one configured at build time.
@@ -111,7 +124,14 @@
registerPackageReceiverIfNeeded();
}
+ /** Called when the system is ready for us to start third-party code. */
+ void systemRunning() {
+ if (DBG) Log.d(TAG, "systemRunning");
+ bindToScoringServiceIfNeeded();
+ }
+
private void registerPackageReceiverIfNeeded() {
+ if (DBG) Log.d(TAG, "registerPackageReceiverIfNeeded");
NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext);
synchronized (mReceiverLock) {
// Unregister the receiver if the current scorer has changed since last registration.
@@ -142,6 +162,41 @@
}
}
+ private void bindToScoringServiceIfNeeded() {
+ if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded");
+ NetworkScorerAppData scorerData = NetworkScorerAppManager.getActiveScorer(mContext);
+ bindToScoringServiceIfNeeded(scorerData);
+ }
+
+ private void bindToScoringServiceIfNeeded(NetworkScorerAppData scorerData) {
+ if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + scorerData + ")");
+ if (scorerData != null && scorerData.mScoringServiceClassName != null) {
+ ComponentName componentName =
+ new ComponentName(scorerData.mPackageName, scorerData.mScoringServiceClassName);
+ // If we're connected to a different component then drop it.
+ if (mServiceConnection != null
+ && !mServiceConnection.mComponentName.equals(componentName)) {
+ unbindFromScoringServiceIfNeeded();
+ }
+
+ // If we're not connected at all then create a new connection.
+ if (mServiceConnection == null) {
+ mServiceConnection = new ScoringServiceConnection(componentName);
+ }
+
+ // Make sure the connection is connected (idempotent)
+ mServiceConnection.connect(mContext);
+ }
+ }
+
+ private void unbindFromScoringServiceIfNeeded() {
+ if (DBG) Log.d(TAG, "unbindFromScoringServiceIfNeeded");
+ if (mServiceConnection != null) {
+ mServiceConnection.disconnect(mContext);
+ }
+ mServiceConnection = null;
+ }
+
@Override
public boolean updateScores(ScoredNetwork[] networks) {
if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) {
@@ -228,8 +283,10 @@
/** Set the active scorer. Callers are responsible for checking permissions as appropriate. */
private boolean setScorerInternal(String packageName) {
+ if (DBG) Log.d(TAG, "setScorerInternal(" + packageName + ")");
long token = Binder.clearCallingIdentity();
try {
+ unbindFromScoringServiceIfNeeded();
// Preemptively clear scores even though the set operation could fail. We do this for
// safety as scores should never be compared across apps; in practice, Settings should
// only be allowing valid apps to be set as scorers, so failure here should be rare.
@@ -237,8 +294,13 @@
// Get the scorer that is about to be replaced, if any, so we can notify it directly.
NetworkScorerAppData prevScorer = NetworkScorerAppManager.getActiveScorer(mContext);
boolean result = NetworkScorerAppManager.setActiveScorer(mContext, packageName);
+ // Unconditionally attempt to bind to the current scorer. If setActiveScorer() failed
+ // then we'll attempt to restore the previous binding (if any), otherwise an attempt
+ // will be made to bind to the new scorer.
+ bindToScoringServiceIfNeeded();
if (result) { // new scorer successfully set
registerPackageReceiverIfNeeded();
+
Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
if (prevScorer != null) { // Directly notify the old scorer.
intent.setPackage(prevScorer.mPackageName);
@@ -295,7 +357,6 @@
return;
}
writer.println("Current scorer: " + currentScorer.mPackageName);
- writer.flush();
for (INetworkScoreCache scoreCache : getScoreCaches()) {
try {
@@ -307,6 +368,12 @@
}
}
}
+ if (mServiceConnection != null) {
+ mServiceConnection.dump(fd, writer, args);
+ } else {
+ writer.println("ScoringServiceConnection: null");
+ }
+ writer.flush();
}
/**
@@ -320,4 +387,50 @@
return new HashSet<>(mScoreCaches.values());
}
}
+
+ private static class ScoringServiceConnection implements ServiceConnection {
+ private final ComponentName mComponentName;
+ private boolean mBound = false;
+
+ ScoringServiceConnection(ComponentName componentName) {
+ mComponentName = componentName;
+ }
+
+ void connect(Context context) {
+ disconnect(context);
+ Intent service = new Intent();
+ service.setComponent(mComponentName);
+ mBound = context.bindServiceAsUser(service, this,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ UserHandle.SYSTEM);
+ if (!mBound) {
+ Log.w(TAG, "Bind call failed for " + service);
+ }
+ }
+
+ void disconnect(Context context) {
+ try {
+ if (mBound) {
+ mBound = false;
+ context.unbindService(this);
+ }
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Unbind failed.", e);
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DBG) Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d741c49..5d1cb8a 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -343,6 +343,25 @@
return null;
}
+ if (!r.startRequested) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Before going further -- if this app is not allowed to run in the
+ // background, then at this point we aren't going to let it period.
+ final int allowed = mAm.checkAllowBackgroundLocked(
+ r.appInfo.uid, r.packageName, callingPid, true);
+ if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
+ Slog.w(TAG, "Background start not allowed: service "
+ + service + " to " + r.name.flattenToShortString()
+ + " from pid=" + callingPid + " uid=" + callingUid
+ + " pkg=" + callingPackage);
+ return null;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
@@ -1274,23 +1293,6 @@
}
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
- final long token = Binder.clearCallingIdentity();
- try {
- // Before going further -- if this app is not allowed to run in the
- // background, then at this point we aren't going to let it period.
- final int allowed = mAm.checkAllowBackgroundLocked(
- sInfo.applicationInfo.uid, sInfo.packageName, callingPid, true);
- if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
- Slog.w(TAG, "Background execution not allowed: service "
- + service + " to " + name.flattenToShortString()
- + " from pid=" + callingPid + " uid=" + callingUid
- + " pkg=" + callingPackage);
- return null;
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
Intent.FilterComparison filter
= new Intent.FilterComparison(service.cloneFilter());
ServiceRestarter res = new ServiceRestarter();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1da6a20..f6f3295 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15456,8 +15456,9 @@
}
for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
- if (oomAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
- || oomIndex == (oomPss.length-1)) {
+ if (oomIndex == (oomPss.length - 1)
+ || (oomAdj >= DUMP_MEM_OOM_ADJ[oomIndex]
+ && oomAdj < DUMP_MEM_OOM_ADJ[oomIndex + 1])) {
oomPss[oomIndex] += myTotalPss;
oomSwapPss[oomIndex] += myTotalSwapPss;
if (oomProcs[oomIndex] == null) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6c09178..f659bde 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1984,6 +1984,8 @@
mTmpConfigs.clear();
mTmpInsetBounds.clear();
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
+ final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
for (int i = tasks.size() - 1; i >= 0; i--) {
final TaskRecord task = tasks.get(i);
if (task.isResizeable()) {
@@ -1995,9 +1997,7 @@
fitWithinBounds(tempRect2, bounds);
task.updateOverrideConfiguration(tempRect2);
} else {
- task.updateOverrideConfiguration(
- tempTaskBounds != null ? tempTaskBounds : bounds,
- tempTaskInsetBounds != null ? tempTaskInsetBounds : bounds);
+ task.updateOverrideConfiguration(taskBounds, insetBounds);
}
}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 7f7ea9d..e9d9628 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -42,10 +42,10 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.FactoryTest;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -59,6 +59,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -74,6 +75,29 @@
public final class ContentService extends IContentService.Stub {
private static final String TAG = "ContentService";
+ public static class Lifecycle extends SystemService {
+ private ContentService mContentService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ final boolean factoryTest = (FactoryTest
+ .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+ mContentService = new ContentService(getContext(), factoryTest);
+ publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mContentService);
+ }
+
+ @Override
+ public void onCleanupUser(int userHandle) {
+ synchronized (mContentService.mCache) {
+ mContentService.mCache.remove(userHandle);
+ }
+ }
+ }
+
private Context mContext;
private boolean mFactoryTest;
@@ -94,12 +118,18 @@
private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final Uri data = intent.getData();
- if (data != null) {
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_NULL);
- final String packageName = data.getSchemeSpecificPart();
- invalidateCacheLocked(userId, packageName, null);
+ synchronized (mCache) {
+ if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+ mCache.clear();
+ } else {
+ final Uri data = intent.getData();
+ if (data != null) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL);
+ final String packageName = data.getSchemeSpecificPart();
+ invalidateCacheLocked(userId, packageName, null);
+ }
+ }
}
}
};
@@ -227,6 +257,11 @@
packageFilter.addDataScheme("package");
mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
packageFilter, null, null);
+
+ final IntentFilter localeFilter = new IntentFilter();
+ localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+ mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
+ localeFilter, null, null);
}
public void systemReady() {
@@ -1080,12 +1115,6 @@
}
}
- public static ContentService main(Context context, boolean factoryTest) {
- ContentService service = new ContentService(context, factoryTest);
- ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
- return service;
- }
-
/**
* Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
* permission, if the userHandle is not for the caller.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4ce730f..f85dce7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12134,8 +12134,23 @@
// predecessor. As a security measure, this is permited only if this is not a
// version downgrade or if the predecessor package is marked as debuggable and
// a downgrade is explicitly requested.
- if (((dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0)
- || ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0)) {
+ //
+ // On debuggable platform builds, downgrades are permitted even for
+ // non-debuggable packages to make testing easier. Debuggable platform builds do
+ // not offer security guarantees and thus it's OK to disable some security
+ // mechanisms to make debugging/testing easier on those builds. However, even on
+ // debuggable builds downgrades of packages are permitted only if requested via
+ // installFlags. This is because we aim to keep the behavior of debuggable
+ // platform builds as close as possible to the behavior of non-debuggable
+ // platform builds.
+ final boolean downgradeRequested =
+ (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+ final boolean packageDebuggable =
+ (dataOwnerPkg.applicationInfo.flags
+ & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+ final boolean downgradePermitted =
+ (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable));
+ if (!downgradePermitted) {
try {
checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 90d500e..06a91fb 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -500,6 +500,9 @@
if (mRemovingUserIds.get(profile.id)) {
continue;
}
+ if (profile.partial) {
+ continue;
+ }
users.add(userWithName(profile));
}
return users;
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 3bfcf00..6bdcd42 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -200,11 +200,11 @@
layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
- // If we have a dock divider ensure the Input Method is above it.
- if (mDockDivider != null && mService.mInputMethodWindow != null) {
+ if (mDockDivider != null && mDockDivider.isVisibleLw()
+ && mService.mInputMethodWindow != null) {
layer = assignAndIncreaseLayerIfNeeded(mService.mInputMethodWindow, layer);
}
-
+
// We know that we will be animating a relaunching window in the near future, which will
// receive a z-order increase. We want the replaced window to immediately receive the same
// treatment, e.g. to be above the dock divider.
@@ -218,7 +218,7 @@
}
private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
- if (win != null) {
+ if (win != null && layer > win.mLayer) {
assignAnimLayer(win, layer);
// Make sure we leave space inbetween normal windows for dims and such.
layer += WINDOW_LAYER_MULTIPLIER;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fd6617a..eba7818 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1369,9 +1369,6 @@
final int fl = w.mAttrs.flags
& (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
final int type = w.mAttrs.type;
- // The dock divider has to sit above the application windows and so does the IME. IME also
- // needs to sit above the dock divider, so it doesn't get cut in half. We make the dock
- // divider be a target for IME, so this relationship can occur naturally.
if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
|| type == TYPE_APPLICATION_STARTING) {
if (DEBUG_INPUT_METHOD) {
@@ -4292,9 +4289,13 @@
wtoken.appDied = false;
wtoken.removeAllWindows();
} else if (visible) {
- mOpeningApps.add(wtoken);
+ if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
+ // Add the app mOpeningApps if transition is unset but ready. This means
+ // we're doing a screen freeze, and the unfreeze will wait for all opening
+ // apps to be ready.
+ mOpeningApps.add(wtoken);
+ }
wtoken.startingMoved = false;
-
// If the token is currently hidden (should be the common case), or has been
// stopped, then we need to set up to wait for its windows to be ready.
if (wtoken.hidden || wtoken.mAppStopped) {
@@ -4338,6 +4339,7 @@
}
wtoken.inPendingTransaction = true;
if (visible) {
+ mOpeningApps.add(wtoken);
wtoken.mEnteringAnimation = true;
} else {
mClosingApps.add(wtoken);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ec86a0190..c62292d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -807,26 +807,31 @@
mContentInsets.setEmpty();
mVisibleInsets.setEmpty();
} else {
- // Using mContentInsets as a temp rect. It is safe because we're setting it below.
- getDisplayContent().getLogicalDisplayRect(mContentInsets);
+ getDisplayContent().getLogicalDisplayRect(mTmpRect);
// Override right and/or bottom insets in case if the frame doesn't fit the screen in
// non-fullscreen mode.
- boolean overrideRightInset = !fullscreenTask && mFrame.right > mContentInsets.right;
- boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mContentInsets.bottom;
+ boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right;
+ boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom;
mContentInsets.set(mContentFrame.left - frame.left,
mContentFrame.top - frame.top,
- overrideRightInset ? 0 : frame.right - mContentFrame.right,
- overrideBottomInset ? 0 : frame.bottom - mContentFrame.bottom);
+ overrideRightInset ? mTmpRect.right - mContentFrame.right
+ : frame.right - mContentFrame.right,
+ overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
+ : frame.bottom - mContentFrame.bottom);
mVisibleInsets.set(mVisibleFrame.left - frame.left,
mVisibleFrame.top - frame.top,
- overrideRightInset ? 0 : frame.right - mVisibleFrame.right,
- overrideBottomInset ? 0 : frame.bottom - mVisibleFrame.bottom);
+ overrideRightInset ? mTmpRect.right - mVisibleFrame.right
+ : frame.right - mVisibleFrame.right,
+ overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
+ : frame.bottom - mVisibleFrame.bottom);
mStableInsets.set(Math.max(mStableFrame.left - frame.left, 0),
Math.max(mStableFrame.top - frame.top, 0),
- overrideRightInset ? 0 : Math.max(frame.right - mStableFrame.right, 0),
- overrideBottomInset ? 0 : Math.max(frame.bottom - mStableFrame.bottom, 0));
+ overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
+ : Math.max(frame.right - mStableFrame.right, 0),
+ overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
+ : Math.max(frame.bottom - mStableFrame.bottom, 0));
}
if (!mInsetFrame.isEmpty()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 37f2302..0d4887d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2805,6 +2805,10 @@
&& getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
throw new IllegalArgumentException("Admin is already added");
}
+ if (policy.mRemovingAdmins.contains(adminReceiver)) {
+ throw new IllegalArgumentException(
+ "Trying to set an admin which is being removed");
+ }
ActiveAdmin newAdmin = new ActiveAdmin(info, /* parent */ false);
policy.mAdminMap.put(adminReceiver, newAdmin);
int replaceIndex = -1;
@@ -3006,7 +3010,7 @@
ArrayList<ActiveAdmin> admins = new ArrayList<ActiveAdmin>();
for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
DevicePolicyData policy = getUserData(userInfo.id);
- if (!isManagedProfile(userInfo.id)) {
+ if (!userInfo.isManagedProfile()) {
admins.addAll(policy.mAdminList);
} else {
// For managed profiles, we always include the policies set on the parent
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 659450e..e7ae2b0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -157,6 +157,8 @@
"com.google.android.clockwork.ThermalObserver";
private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
"com.google.android.clockwork.bluetooth.WearBluetoothService";
+ private static final String CONTENT_SERVICE_CLASS =
+ "com.android.server.content.ContentService$Lifecycle";
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
@@ -574,8 +576,7 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("StartContentService");
- contentService = ContentService.main(context,
- mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+ mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("InstallSystemProviders");
@@ -1324,7 +1325,7 @@
reportWtf("starting System UI", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeMountServiceReady");
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkScoreReady");
try {
if (networkScoreF != null) networkScoreF.systemReady();
} catch (Throwable e) {
@@ -1423,6 +1424,12 @@
} catch (Throwable e) {
reportWtf("Notifying MmsService running", e);
}
+
+ try {
+ if (networkScoreF != null) networkScoreF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying NetworkScoreService running", e);
+ }
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
});
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index 38ede87..46ce7a0 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -127,6 +127,14 @@
public void setReceiver(MidiReceiver receiver) {
mReceiver = receiver;
}
+
+ @Override
+ public void onFlush() throws IOException {
+ MidiReceiver receiver = mReceiver;
+ if (receiver != null) {
+ receiver.flush();
+ }
+ }
}
public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4fa8fe9..6eafb90 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1433,25 +1433,6 @@
}
/**
- * Launches the {@link android.app.Activity} to manage blocked numbers.
- * <p> This method displays the UI to manage blocked numbers only if
- * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
- * {@code true} for the current user.
- * @deprecated Use {@link #createManageBlockedNumbersIntent()} instead.
- */
- // TODO: Delete this.
- public void launchManageBlockedNumbersActivity() {
- ITelecomService service = getTelecomService();
- if (service != null) {
- try {
- service.launchManageBlockedNumbersActivity(mContext.getPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecomService#manageBlockedNumbers", e);
- }
- }
- }
-
- /**
* Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
* launch the activity to manage blocked numbers.
* <p> The activity will display the UI to manage blocked numbers only if
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 3c250f1..871565d 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -246,12 +246,6 @@
boolean setDefaultDialer(in String packageName);
/**
- * @see TelecomServiceImpl#launchManageBlockedNumbersActivity
- **/
- // TODO: Delete this.
- void launchManageBlockedNumbersActivity(in String callingPackageName);
-
- /**
* @see TelecomServiceImpl#createManageBlockedNumbersIntent
**/
Intent createManageBlockedNumbersIntent();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b482811..865af78 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3550,7 +3550,7 @@
* @return the response of ISIM Authetification, or null if not available
* @hide
* @deprecated
- * @see getIccSimChallengeResponse with appType=PhoneConstants.APPTYPE_ISIM
+ * @see getIccAuthentication with appType=PhoneConstants.APPTYPE_ISIM
*/
public String getIsimChallengeResponse(String nonce){
try {
@@ -3566,21 +3566,60 @@
}
}
+ // ICC SIM Application Types
+ public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
+ public static final int APPTYPE_USIM = PhoneConstants.APPTYPE_USIM;
+ public static final int APPTYPE_RUIM = PhoneConstants.APPTYPE_RUIM;
+ public static final int APPTYPE_CSIM = PhoneConstants.APPTYPE_CSIM;
+ public static final int APPTYPE_ISIM = PhoneConstants.APPTYPE_ISIM;
+ // authContext (parameter P2) when doing SIM challenge,
+ // per 3GPP TS 31.102 (Section 7.1.2)
+ public static final int AUTHTYPE_EAP_SIM = PhoneConstants.AUTH_CONTEXT_EAP_SIM;
+ public static final int AUTHTYPE_EAP_AKA = PhoneConstants.AUTH_CONTEXT_EAP_AKA;
+
/**
- * Returns the response of SIM Authentication through RIL.
- * Returns null if the Authentication hasn't been successful
- * @param subId subscription ID to be queried
- * @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
- * @param data authentication challenge data
- * @return the response of SIM Authentication, or null if not available
- * @hide
+ * Returns the response of authentication for the default subscription.
+ * Returns null if the authentication hasn't been successful
+ *
+ * <p>Requires that the calling app has carrier privileges or READ_PRIVILEGED_PHONE_STATE
+ * permission.
+ *
+ * @param appType the icc application type, like {@link #APPTYPE_USIM}
+ * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
+ * {@link #AUTHTYPE_EAP_SIM}
+ * @param data authentication challenge data, base64 encoded.
+ * See 3GPP TS 31.102 7.1.2 for more details.
+ * @return the response of authentication, or null if not available
+ *
+ * @see #hasCarrierPrivileges
*/
- public String getIccSimChallengeResponse(int subId, int appType, String data) {
+ public String getIccAuthentication(int appType, int authType, String data) {
+ return getIccAuthentication(getDefaultSubscription(), appType, authType, data);
+ }
+
+ /**
+ * Returns the response of USIM Authentication for specified subId.
+ * Returns null if the authentication hasn't been successful
+ *
+ * <p>Requires that the calling app has carrier privileges.
+ *
+ * @param subId subscription ID used for authentication
+ * @param appType the icc application type, like {@link #APPTYPE_USIM}
+ * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
+ * {@link #AUTHTYPE_EAP_SIM}
+ * @param data authentication challenge data, base64 encoded.
+ * See 3GPP TS 31.102 7.1.2 for more details.
+ * @return the response of authentication, or null if not available
+ *
+ * @see #hasCarrierPrivileges
+ */
+
+ public String getIccAuthentication(int subId, int appType, int authType, String data) {
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getIccSimChallengeResponse(subId, appType, data);
+ return info.getIccSimChallengeResponse(subId, appType, authType, data);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3599,9 +3638,10 @@
* @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
* @param data authentication challenge data
* @return the response of SIM Authentication, or null if not available
+ * @hide
*/
public String getIccSimChallengeResponse(int appType, String data) {
- return getIccSimChallengeResponse(getDefaultSubscription(), appType, data);
+ return getIccAuthentication(getDefaultSubscription(), appType, AUTHTYPE_EAP_SIM, data);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index dc2b297..02baa34 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -196,8 +196,9 @@
*
* @param subId subscription ID to be queried
* @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
+ * @param authType Authentication type, see PhoneConstants#AUTHTYPE_xxx
* @param data authentication challenge data
* @return challenge response
*/
- String getIccSimChallengeResponse(int subId, int appType, String data);
+ String getIccSimChallengeResponse(int subId, int appType, int authType, String data);
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index ecd89ed..1680fe3 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -202,4 +202,10 @@
public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0;
public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1;
public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER;
+
+ // authContext (parameter P2) when doing SIM challenge,
+ // per 3GPP TS 31.102 (Section 7.1.2)
+ public static final int AUTH_CONTEXT_EAP_SIM = 128;
+ public static final int AUTH_CONTEXT_EAP_AKA = 129;
+ public static final int AUTH_CONTEXT_UNDEFINED = -1;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 4161307..2399b3a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -110,13 +110,13 @@
public final class BridgeContext extends Context {
/** The map adds cookies to each view so that IDE can link xml tags to views. */
- private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
+ private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
/**
* In some cases, when inflating an xml, some objects are created. Then later, the objects are
* converted to views. This map stores the mapping from objects to cookies which can then be
* used to populate the mViewKeyMap.
*/
- private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>();
+ private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
private final BridgeAssetManager mAssets;
private Resources mSystemResources;
private final Object mProjectKey;
@@ -132,8 +132,7 @@
private Resources.Theme mTheme;
- private final Map<Object, Map<String, String>> mDefaultPropMaps =
- new IdentityHashMap<Object, Map<String,String>>();
+ private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>();
// maps for dynamically generated id representing style objects (StyleResourceValue)
@Nullable
@@ -142,13 +141,12 @@
private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
// cache for TypedArray generated from StyleResourceValue object
- private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>
- mTypedArrayCache;
+ private TypedArrayCache mTypedArrayCache;
private BridgeInflater mBridgeInflater;
private BridgeContentResolver mContentResolver;
- private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
+ private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
private SharedPreferences mSharedPreferences;
private ClassLoader mClassLoader;
private IBinder mBinder;
@@ -162,7 +160,7 @@
* This a map from value to attribute name. Warning for missing references shouldn't be logged
* if value and attr name pair is the same as an entry in this map.
*/
- private static Map<String, String> RTL_ATTRS = new HashMap<String, String>(10);
+ private static Map<String, String> RTL_ATTRS = new HashMap<>(10);
static {
RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart");
@@ -325,11 +323,11 @@
return mParserStack.get(mParserStack.size() - 2);
}
- public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
- Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
+ public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
+ Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId);
boolean isFrameworkRes = true;
if (resourceInfo == null) {
- resourceInfo = mLayoutlibCallback.resolveResourceId(resid);
+ resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
isFrameworkRes = false;
}
@@ -602,23 +600,20 @@
@Override
public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
- // No style is specified here, so create the typed array based on the default theme
- // and the styles already applied to it. A null value of style indicates that the default
- // theme should be used.
- return createStyleBasedTypedArray(null, attrs);
+ return obtainStyledAttributes(0, attrs);
}
@Override
- public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs)
+ public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs)
throws Resources.NotFoundException {
StyleResourceValue style = null;
// get the StyleResourceValue based on the resId;
- if (resid != 0) {
- style = getStyleByDynamicId(resid);
+ if (resId != 0) {
+ style = getStyleByDynamicId(resId);
if (style == null) {
// In some cases, style may not be a dynamic id, so we do a full search.
- ResourceReference ref = resolveId(resid);
+ ResourceReference ref = resolveId(resId);
if (ref != null) {
style = mRenderResources.getStyle(ref.getName(), ref.isFramework());
}
@@ -629,41 +624,33 @@
}
}
- // The map is from
- // attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array.
if (mTypedArrayCache == null) {
- mTypedArrayCache = new IdentityHashMap<int[],
- Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>();
+ mTypedArrayCache = new TypedArrayCache();
}
- // get the 2nd map
- Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 =
- mTypedArrayCache.get(attrs);
- if (map2 == null) {
- map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>();
- mTypedArrayCache.put(attrs, map2);
- }
-
- // get the 3rd map
List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
- Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes);
- if (map3 == null) {
- map3 = new HashMap<Integer, BridgeTypedArray>();
- // Create a copy of the list before adding it to the map. This allows reusing the
- // existing list.
- currentThemes = new ArrayList<StyleResourceValue>(currentThemes);
- map2.put(currentThemes, map3);
+
+ Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair =
+ mTypedArrayCache.get(attrs, currentThemes, resId);
+
+ if (typeArrayAndPropertiesPair == null) {
+ typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs);
+ mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair);
}
-
- // get the array from the 3rd map
- BridgeTypedArray ta = map3.get(resid);
-
- if (ta == null) {
- ta = createStyleBasedTypedArray(style, attrs);
- map3.put(resid, ta);
+ // Add value to defaultPropsMap if needed
+ if (typeArrayAndPropertiesPair.getSecond() != null) {
+ Object key = getCurrentParser().getViewCookie();
+ if (key != null) {
+ PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
+ if (defaultPropMap == null) {
+ defaultPropMap = typeArrayAndPropertiesPair.getSecond();
+ mDefaultPropMaps.put(key, defaultPropMap);
+ } else {
+ defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond());
+ }
+ }
}
-
- return ta;
+ return typeArrayAndPropertiesPair.getFirst();
}
@Override
@@ -675,7 +662,7 @@
public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
int defStyleAttr, int defStyleRes) {
- Map<String, String> defaultPropMap = null;
+ PropertiesMap defaultPropMap = null;
boolean isPlatformFile = true;
// Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
@@ -689,7 +676,7 @@
if (key != null) {
defaultPropMap = mDefaultPropMaps.get(key);
if (defaultPropMap == null) {
- defaultPropMap = new HashMap<String, String>();
+ defaultPropMap = new PropertiesMap();
mDefaultPropMaps.put(key, defaultPropMap);
}
}
@@ -937,32 +924,33 @@
*
* @see #obtainStyledAttributes(int, int[])
*/
- private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style,
- int[] attrs) throws Resources.NotFoundException {
-
+ private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
+ @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
- BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length,
- false);
+ BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
+ PropertiesMap defaultPropMap = new PropertiesMap();
// for each attribute, get its name so that we can search it in the style
- for (int i = 0 ; i < attrs.length ; i++) {
+ for (int i = 0; i < attrs.length; i++) {
Pair<String, Boolean> attribute = attributes.get(i);
if (attribute != null) {
// look for the value in the given style
ResourceValue resValue;
+ String attrName = attribute.getFirst();
if (style != null) {
- resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+ resValue = mRenderResources.findItemInStyle(style, attrName,
attribute.getSecond());
} else {
- resValue = mRenderResources.findItemInTheme(attribute.getFirst(),
- attribute.getSecond());
+ resValue = mRenderResources.findItemInTheme(attrName, attribute.getSecond());
}
if (resValue != null) {
+ // Add it to defaultPropMap before resolving
+ defaultPropMap.put(attrName, resValue.getValue());
// resolve it to make sure there are no references left.
- ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
+ ta.bridgeSetValue(i, attrName, attribute.getSecond(),
mRenderResources.resolveResValue(resValue));
}
}
@@ -970,7 +958,7 @@
ta.sealArray();
- return ta;
+ return Pair.of(ta, defaultPropMap);
}
/**
@@ -982,7 +970,7 @@
* @return List of attribute information.
*/
private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
- List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
+ List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
// for each attribute, get its name so that we can search it in the style
for (int attr : attrs) {
@@ -1011,7 +999,7 @@
* @return A (name, isFramework) pair describing the attribute if found. Returns null
* if nothing is found.
*/
- public Pair<String, Boolean> searchAttr(int attr) {
+ private Pair<String, Boolean> searchAttr(int attr) {
Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
if (info != null) {
return Pair.of(info.getSecond(), Boolean.TRUE);
@@ -1028,8 +1016,8 @@
public int getDynamicIdByStyle(StyleResourceValue resValue) {
if (mDynamicIdToStyleMap == null) {
// create the maps.
- mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>();
- mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>();
+ mDynamicIdToStyleMap = new HashMap<>();
+ mStyleToDynamicIdMap = new HashMap<>();
}
// look for an existing id
@@ -1868,4 +1856,69 @@
public boolean isCredentialProtectedStorage() {
return false;
}
+
+
+ /**
+ * The cached value depends on
+ * <ol>
+ * <li>{@code int[]}: the attributes for which TypedArray is created </li>
+ * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
+ * creation of the TypedArray</li>
+ * <li>{@code Integer}: the default style used at the time of creation</li>
+ * </ol>
+ *
+ * The class is created by using nested maps resolving one dependency at a time.
+ * <p/>
+ * The final value of the nested maps is a pair of the typed array and a map of properties
+ * that should be added to {@link #mDefaultPropMaps}, if needed.
+ */
+ private static class TypedArrayCache {
+
+ private Map<int[],
+ Map<List<StyleResourceValue>,
+ Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
+
+ public TypedArrayCache() {
+ mCache = new IdentityHashMap<>();
+ }
+
+ public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
+ List<StyleResourceValue> themes, int resId) {
+ Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
+ cacheFromThemes = mCache.get(attrs);
+ if (cacheFromThemes != null) {
+ Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
+ cacheFromThemes.get(themes);
+ if (cacheFromResId != null) {
+ return cacheFromResId.get(resId);
+ }
+ }
+ return null;
+ }
+
+ public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
+ Pair<BridgeTypedArray, PropertiesMap> value) {
+ Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
+ cacheFromThemes = mCache.get(attrs);
+ if (cacheFromThemes == null) {
+ cacheFromThemes = new HashMap<>();
+ mCache.put(attrs, cacheFromThemes);
+ }
+ Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
+ cacheFromThemes.get(themes);
+ if (cacheFromResId == null) {
+ cacheFromResId = new HashMap<>();
+ cacheFromThemes.put(themes, cacheFromResId);
+ }
+ cacheFromResId.put(resId, value);
+ }
+
+ }
+
+ /**
+ * An alias used for the value in {@code {@link #mDefaultPropMaps}}
+ */
+ private static class PropertiesMap extends HashMap<String, String> {
+ }
+
}