Merge "Update GrContext creation calls to use sk_sp"
diff --git a/Android.bp b/Android.bp
index 82589c1..40757a9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -545,6 +545,7 @@
"core/java/android/net/EventLogTags.logtags",
"core/java/android/webkit/EventLogTags.logtags",
"core/java/com/android/internal/logging/EventLogTags.logtags",
+ "core/java/com/android/server/DropboxLogTags.logtags",
":framework-statslog-gen",
],
diff --git a/Android.mk b/Android.mk
index 10d11f3..9676958 100644
--- a/Android.mk
+++ b/Android.mk
@@ -486,6 +486,10 @@
include $(BUILD_APIDIFF)
+# Hack to get diffs included in docs output
+out_zip := $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
+$(out_zip): $(full_target)
+
# ==== System API diff ===========================
include $(CLEAR_VARS)
@@ -512,6 +516,10 @@
include $(BUILD_APIDIFF)
+# Hack to get diffs included in docs output
+out_zip := $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
+$(out_zip): $(full_target)
+
# ==== the api stubs and current.xml ===========================
include $(CLEAR_VARS)
@@ -656,10 +664,6 @@
# Check comment when you are updating the API
update-api: doc-comment-check-docs
-# Generate API diffs as part of docs builds
-docs: offline-sdk-referenceonly-diff
-docs: offline-system-sdk-referenceonly-diff
-
# ==== static html in the sdk ==================================
include $(CLEAR_VARS)
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk
index f08b402..75cb229 100644
--- a/apct-tests/perftests/core/Android.mk
+++ b/apct-tests/perftests/core/Android.mk
@@ -11,8 +11,9 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
apct-perftests-utils \
- guava \
- legacy-android-test
+ guava
+
+LOCAL_JAVA_LIBRARIES := android.test.base
LOCAL_PACKAGE_NAME := CorePerfTests
diff --git a/api/current.txt b/api/current.txt
index f56f1a1..c3dbee0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3952,6 +3952,7 @@
field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
field public static final int IMPORTANCE_CACHED = 400; // 0x190
+ field public static final int IMPORTANCE_CANT_SAVE_STATE = 270; // 0x10e
field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
@@ -6393,7 +6394,7 @@
method public deprecated boolean isCallerApplicationRestrictionsManagingPackage();
method public boolean isDeviceOwnerApp(java.lang.String);
method public boolean isLockTaskPermitted(java.lang.String);
- method public boolean isLogoutButtonEnabled();
+ method public boolean isLogoutEnabled();
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
@@ -6437,7 +6438,7 @@
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskFeatures(android.content.ComponentName, int);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
- method public void setLogoutButtonEnabled(android.content.ComponentName, boolean);
+ method public void setLogoutEnabled(android.content.ComponentName, boolean);
method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -20558,6 +20559,7 @@
method public int getMaxWidth();
method public java.lang.CharSequence getTextForImeAction(int);
method public android.app.Dialog getWindow();
+ method public void hideSoftInputFromInputMethod(int);
method public void hideStatusIcon();
method public void hideWindow();
method public boolean isExtractViewShown();
@@ -20613,10 +20615,16 @@
method public void setCandidatesViewShown(boolean);
method public void setExtractView(android.view.View);
method public void setExtractViewShown(boolean);
+ method public void setInputMethod(java.lang.String);
+ method public void setInputMethodAndSubtype(java.lang.String, android.view.inputmethod.InputMethodSubtype);
method public void setInputView(android.view.View);
+ method public boolean shouldOfferSwitchingToNextInputMethod();
+ method public void showSoftInputFromInputMethod(int);
method public void showStatusIcon(int);
method public void showWindow(boolean);
method public void switchInputMethod(java.lang.String);
+ method public boolean switchToLastInputMethod();
+ method public boolean switchToNextInputMethod(boolean);
method public void updateFullscreenMode();
method public void updateInputViewShown();
field public static final int BACK_DISPOSITION_DEFAULT = 0; // 0x0
@@ -49034,10 +49042,10 @@
method public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodList();
method public android.view.inputmethod.InputMethodSubtype getLastInputMethodSubtype();
method public java.util.Map<android.view.inputmethod.InputMethodInfo, java.util.List<android.view.inputmethod.InputMethodSubtype>> getShortcutInputMethodsAndSubtypes();
- method public void hideSoftInputFromInputMethod(android.os.IBinder, int);
+ method public deprecated void hideSoftInputFromInputMethod(android.os.IBinder, int);
method public boolean hideSoftInputFromWindow(android.os.IBinder, int);
method public boolean hideSoftInputFromWindow(android.os.IBinder, int, android.os.ResultReceiver);
- method public void hideStatusIcon(android.os.IBinder);
+ method public deprecated void hideStatusIcon(android.os.IBinder);
method public boolean isAcceptingText();
method public boolean isActive(android.view.View);
method public boolean isActive();
@@ -49047,17 +49055,17 @@
method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
method public boolean setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
- method public void setInputMethod(android.os.IBinder, java.lang.String);
- method public void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
- method public boolean shouldOfferSwitchingToNextInputMethod(android.os.IBinder);
+ method public deprecated void setInputMethod(android.os.IBinder, java.lang.String);
+ method public deprecated void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
+ method public deprecated boolean shouldOfferSwitchingToNextInputMethod(android.os.IBinder);
method public void showInputMethodAndSubtypeEnabler(java.lang.String);
method public void showInputMethodPicker();
method public boolean showSoftInput(android.view.View, int);
method public boolean showSoftInput(android.view.View, int, android.os.ResultReceiver);
- method public void showSoftInputFromInputMethod(android.os.IBinder, int);
- method public void showStatusIcon(android.os.IBinder, java.lang.String, int);
- method public boolean switchToLastInputMethod(android.os.IBinder);
- method public boolean switchToNextInputMethod(android.os.IBinder, boolean);
+ method public deprecated void showSoftInputFromInputMethod(android.os.IBinder, int);
+ method public deprecated void showStatusIcon(android.os.IBinder, java.lang.String, int);
+ method public deprecated boolean switchToLastInputMethod(android.os.IBinder);
+ method public deprecated boolean switchToNextInputMethod(android.os.IBinder, boolean);
method public void toggleSoftInput(int, int);
method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
method public deprecated void updateCursor(android.view.View, int, int, int, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 3c3521f..27e585d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -162,6 +162,10 @@
method public abstract boolean isPermissionReviewModeEnabled();
}
+ public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
+ }
+
public final class ShortcutInfo implements android.os.Parcelable {
method public boolean isVisibleToPublisher();
}
diff --git a/cmds/statsd/src/atoms_copy.proto b/cmds/statsd/src/atoms_copy.proto
index 18b2144..72bb38a 100644
--- a/cmds/statsd/src/atoms_copy.proto
+++ b/cmds/statsd/src/atoms_copy.proto
@@ -48,12 +48,14 @@
SyncStateChanged sync_state_changed = 7;
ScheduledJobStateChanged scheduled_job_state_changed = 8;
ScreenBrightnessChanged screen_brightness_changed = 9;
- // 10-20 are temporarily reserved for wakelocks etc.
WakelockStateChanged wakelock_state_changed = 10;
- UidWakelockStateChanged uid_wakelock_state_changed = 11;
- LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 12;
- BatterySaverModeStateChanged battery_saver_mode_state_changed = 21;
- DeviceIdleModeStateChanged device_idle_mode_state_changed = 22;
+ LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 11;
+ MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12;
+ WifiRadioPowerStateChanged wifi_radio_power_state_changed = 13;
+ // TODO: 14-19 are blank, but need not be
+ BatterySaverModeStateChanged battery_saver_mode_state_changed = 20;
+ DeviceIdleModeStateChanged device_idle_mode_state_changed = 21;
+ DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22;
AudioStateChanged audio_state_changed = 23;
MediaCodecActivityChanged media_codec_activity_changed = 24;
CameraStateChanged camera_state_changed = 25;
@@ -75,6 +77,8 @@
SettingChanged setting_changed = 41;
ActivityForegroundStateChanged activity_foreground_state_changed = 42;
IsolatedUidChanged isolated_uid_changed = 43;
+ PacketWakeupOccurred packet_wakeup_occurred = 44;
+ DropboxErrorChanged dropbox_error_changed = 45;
// TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
}
@@ -91,6 +95,8 @@
CpuTimePerFreqPulled cpu_time_per_freq_pulled = 1008;
CpuTimePerUidPulled cpu_time_per_uid_pulled = 1009;
CpuTimePerUidFreqPulled cpu_time_per_uid_freq_pulled = 1010;
+ WifiActivityEnergyInfoPulled wifi_activity_energy_info_pulled = 1011;
+ ModemActivityInfoPulled modem_activity_info_pulled = 1012;
}
}
@@ -147,6 +153,7 @@
STATE_DOZE = 3;
STATE_DOZE_SUSPEND = 4;
STATE_VR = 5;
+ STATE_ON_SUSPEND = 6;
}
// New screen state.
optional State display_state = 1;
@@ -179,13 +186,17 @@
// TODO: What is this?
optional string name = 2;
- // The state.
- // TODO: Use an enum.
- optional int32 event = 3;
+ // What lifecycle state the process changed to.
+ // This enum is specific to atoms.proto.
+ enum Event {
+ PROCESS_FINISHED = 0;
+ PROCESS_STARTED = 1;
+ PROCESS_CRASHED = 2;
+ PROCESS_ANRED = 3;
+ }
+ optional Event event = 3;
}
-
-
/**
* Logs when the ble scan state changes.
*
@@ -417,31 +428,6 @@
}
/**
- * Logs when an app is holding a wakelock, regardless of the wakelock's name.
- *
- * Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
- */
-message UidWakelockStateChanged {
- // TODO: Add attribution instead of uid.
- optional int32 uid = 1;
-
- // Type of wakelock.
- enum Type {
- PARTIAL = 0;
- FULL = 1;
- WINDOW = 2;
- }
- optional Type type = 2;
-
- enum State {
- OFF = 0;
- ON = 1;
- }
- optional State state = 3;
-}
-
-/**
* Logs when a partial wakelock is considered 'long' (over 1 min).
*
* Logged from:
@@ -482,11 +468,33 @@
* Logs Doze mode state change.
*
* Logged from:
- * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
+ * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message DeviceIdleModeStateChanged {
// TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_.
- optional int32 state = 1;
+ enum State {
+ DEVICE_IDLE_MODE_OFF = 0;
+ DEVICE_IDLE_MODE_LIGHT = 1;
+ DEVICE_IDLE_MODE_DEEP = 2;
+ }
+ optional State state = 1;
+}
+
+
+/**
+ * Logs state change of Doze mode including maintenance windows.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message DeviceIdlingModeStateChanged {
+ // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_.
+ enum State {
+ DEVICE_IDLE_MODE_OFF = 0;
+ DEVICE_IDLE_MODE_LIGHT = 1;
+ DEVICE_IDLE_MODE_DEEP = 2;
+ }
+ optional State state = 1;
}
/**
@@ -586,6 +594,49 @@
message WakeupAlarmOccurred {
// TODO: Add attribution instead of uid?
optional int32 uid = 1;
+
+ // Name of the wakeup alarm.
+ optional string tag = 2;
+}
+
+/**
+ * Logs when an an app causes the mobile radio to change state.
+ * Changing from LOW to MEDIUM or HIGH can be considered the app waking the mobile radio.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message MobileRadioPowerStateChanged {
+ // TODO: Add attribution instead of uid?
+ optional int32 uid = 1;
+
+ // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states.
+ enum PowerState {
+ DC_POWER_STATE_LOW = 1;
+ DC_POWER_STATE_MEDIUM = 2;
+ DC_POWER_STATE_HIGH = 3;
+ }
+ optional PowerState power_state = 2;
+}
+
+/**
+ * Logs when an an app causes the wifi radio to change state.
+ * Changing from LOW to MEDIUM or HIGH can be considered the app waking the wifi radio.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message WifiRadioPowerStateChanged {
+ // TODO: Add attribution instead of uid?
+ optional int32 uid = 1;
+
+ // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states.
+ enum PowerState {
+ DC_POWER_STATE_LOW = 1;
+ DC_POWER_STATE_MEDIUM = 2;
+ DC_POWER_STATE_HIGH = 3;
+ }
+ optional PowerState power_state = 2;
}
/**
@@ -705,7 +756,7 @@
optional int32 user = 7;
}
-/*
+/**
* Logs activity going to foreground or background
*
* Logged from:
@@ -723,6 +774,34 @@
}
/**
+ * Logs when an error is written to dropbox.
+ * Logged from:
+ * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message DropboxErrorChanged {
+ // The uid if available. -1 means not available.
+ optional int32 uid = 1;
+
+ // Tag used when recording this error to dropbox. Contains data_ or system_ prefix.
+ optional string tag = 2;
+
+ // The name of the process.
+ optional string process_name = 3;
+
+ // The pid if available. -1 means not available.
+ optional int32 pid = 4;
+
+ // 1 indicates is instant app. -1 indicates Not applicable.
+ optional int32 is_instant_app = 5;
+
+ // The activity name if available.
+ optional string activity_name = 6;
+
+ // 1 indicates in foreground. -1 indicates not available.
+ optional int32 is_foreground = 7;
+}
+
+/**
* Pulls bytes transferred via wifi (Sum of foreground and background usage).
*
* Pulled from:
@@ -817,7 +896,7 @@
optional int64 time = 4;
}
-/*
+/**
* Pulls PowerStatePlatformSleepState.
*
* Definition here:
@@ -877,7 +956,7 @@
optional int32 is_create = 3;
}
-/*
+/**
* Pulls Cpu time per frequency.
* Note: this should be pulled for gauge metric only, without condition.
* The puller keeps internal state of last values. It should not be pulled by
@@ -894,7 +973,7 @@
optional uint64 time = 3;
}
-/*
+/**
* Pulls Cpu Time Per Uid.
* Note that isolated process uid time should be attributed to host uids.
*/
@@ -913,4 +992,86 @@
optional uint64 uid = 1;
optional uint64 freq_idx = 2;
optional uint64 time_ms = 3;
+}
+
+/*
+ * Logs the reception of an incoming network packet causing the main system to wake up for
+ * processing that packet. These events are notified by the kernel via Netlink NFLOG to Netd
+ * and processed by WakeupController.cpp.
+ */
+message PacketWakeupOccurred {
+ // The uid owning the socket into which the packet was delivered, or -1 if the packet was
+ // delivered nowhere.
+ optional int32 uid = 1;
+ // The interface name on which the packet was received.
+ optional string iface = 2;
+ // The ethertype value of the packet.
+ optional int32 ethertype = 3;
+ // String representation of the destination MAC address of the packet.
+ optional string destination_hardware_address = 4;
+ // String representation of the source address of the packet if this was an IP packet.
+ optional string source_ip = 5;
+ // String representation of the destination address of the packet if this was an IP packet.
+ optional string destination_ip = 6;
+ // The value of the protocol field if this was an IPv4 packet or the value of the Next Header
+ // field if this was an IPv6 packet. The range of possible values is the same for both IP
+ // families.
+ optional int32 ip_next_header = 7;
+ // The source port if this was a TCP or UDP packet.
+ optional int32 source_port = 8;
+ // The destination port if this was a TCP or UDP packet.
+ optional int32 destination_port = 9;
+}
+
+/**
+ * Pulls Wifi Controller Activity Energy Info
+ */
+message WifiActivityEnergyInfoPulled {
+ // timestamp(wall clock) of record creation
+ optional uint64 timestamp_ms = 1;
+ // stack reported state
+ // TODO: replace this with proto enum
+ optional int32 stack_state = 2;
+ // tx time in ms
+ optional uint64 controller_tx_time_ms = 3;
+ // rx time in ms
+ optional uint64 controller_rx_time_ms = 4;
+ // idle time in ms
+ optional uint64 controller_idle_time_ms = 5;
+ // product of current(mA), voltage(V) and time(ms)
+ optional uint64 controller_energy_used = 6;
+}
+
+/**
+ * Pulls Modem Activity Energy Info
+ */
+message ModemActivityInfoPulled {
+ // timestamp(wall clock) of record creation
+ optional uint64 timestamp_ms = 1;
+ // sleep time in ms.
+ optional uint64 sleep_time_ms = 2;
+ // idle time in ms
+ optional uint64 controller_idle_time_ms = 3;
+ /**
+ * Tx power index
+ * index 0 = tx_power < 0dBm
+ * index 1 = 0dBm < tx_power < 5dBm
+ * index 2 = 5dBm < tx_power < 15dBm
+ * index 3 = 15dBm < tx_power < 20dBm
+ * index 4 = tx_power > 20dBm
+ */
+ // tx time in ms at power level 0
+ optional uint64 controller_tx_time_pl0_ms = 4;
+ // tx time in ms at power level 1
+ optional uint64 controller_tx_time_pl1_ms = 5;
+ // tx time in ms at power level 2
+ optional uint64 controller_tx_time_pl2_ms = 6;
+ // tx time in ms at power level 3
+ optional uint64 controller_tx_time_pl3_ms = 7;
+ // tx time in ms at power level 4
+ optional uint64 controller_tx_time_pl4_ms = 8;
+ // rx time in ms at power level 5
+ optional uint64 controller_rx_time_ms = 9;
+ // product of current(mA), voltage(V) and time(ms)
+ optional uint64 energy_used = 10;
}
\ No newline at end of file
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
index 5e8f26d..735a327 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
@@ -110,113 +110,7 @@
log.getEventMetrics();
for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) {
sb.append(getDateStr(event.getTimestampNanos())).append(": ");
- switch (event.getAtom().getPushedCase()) {
- case SETTING_CHANGED:
- sb.append("SETTING_CHANGED\n");
- break;
- case SYNC_STATE_CHANGED:
- sb.append("SYNC_STATE_CHANGED\n");
- break;
- case AUDIO_STATE_CHANGED:
- sb.append("AUDIO_STATE_CHANGED\n");
- break;
- case CAMERA_STATE_CHANGED:
- sb.append("CAMERA_STATE_CHANGED\n");
- break;
- case ISOLATED_UID_CHANGED:
- sb.append("ISOLATED_UID_CHANGED\n");
- break;
- case SCREEN_STATE_CHANGED:
- sb.append("SCREEN_STATE_CHANGED\n");
- break;
- case SENSOR_STATE_CHANGED:
- sb.append("SENSOR_STATE_CHANGED\n");
- break;
- case BATTERY_LEVEL_CHANGED:
- sb.append("BATTERY_LEVEL_CHANGED\n");
- break;
- case PLUGGED_STATE_CHANGED:
- sb.append("PLUGGED_STATE_CHANGED\n");
- break;
- case WAKEUP_ALARM_OCCURRED:
- sb.append("WAKEUP_ALARM_OCCURRED\n");
- break;
- case BLE_SCAN_STATE_CHANGED:
- sb.append("BLE_SCAN_STATE_CHANGED\n");
- break;
- case CHARGING_STATE_CHANGED:
- sb.append("CHARGING_STATE_CHANGED\n");
- break;
- case GPS_SCAN_STATE_CHANGED:
- sb.append("GPS_SCAN_STATE_CHANGED\n");
- break;
- case KERNEL_WAKEUP_REPORTED:
- sb.append("KERNEL_WAKEUP_REPORTED\n");
- break;
- case WAKELOCK_STATE_CHANGED:
- sb.append("WAKELOCK_STATE_CHANGED\n");
- break;
- case WIFI_LOCK_STATE_CHANGED:
- sb.append("WIFI_LOCK_STATE_CHANGED\n");
- break;
- case WIFI_SCAN_STATE_CHANGED:
- sb.append("WIFI_SCAN_STATE_CHANGED\n");
- break;
- case BLE_SCAN_RESULT_RECEIVED:
- sb.append("BLE_SCAN_RESULT_RECEIVED\n");
- break;
- case DEVICE_ON_STATUS_CHANGED:
- sb.append("DEVICE_ON_STATUS_CHANGED\n");
- break;
- case FLASHLIGHT_STATE_CHANGED:
- sb.append("FLASHLIGHT_STATE_CHANGED\n");
- break;
- case SCREEN_BRIGHTNESS_CHANGED:
- sb.append("SCREEN_BRIGHTNESS_CHANGED\n");
- break;
- case UID_PROCESS_STATE_CHANGED:
- sb.append("UID_PROCESS_STATE_CHANGED\n");
- break;
- case UID_WAKELOCK_STATE_CHANGED:
- sb.append("UID_WAKELOCK_STATE_CHANGED\n");
- break;
- case DEVICE_TEMPERATURE_REPORTED:
- sb.append("DEVICE_TEMPERATURE_REPORTED\n");
- break;
- case SCHEDULED_JOB_STATE_CHANGED:
- sb.append("SCHEDULED_JOB_STATE_CHANGED\n");
- break;
- case MEDIA_CODEC_ACTIVITY_CHANGED:
- sb.append("MEDIA_CODEC_ACTIVITY_CHANGED\n");
- break;
- case WIFI_SIGNAL_STRENGTH_CHANGED:
- sb.append("WIFI_SIGNAL_STRENGTH_CHANGED\n");
- break;
- case PHONE_SIGNAL_STRENGTH_CHANGED:
- sb.append("PHONE_SIGNAL_STRENGTH_CHANGED\n");
- break;
- case DEVICE_IDLE_MODE_STATE_CHANGED:
- sb.append("DEVICE_IDLE_MODE_STATE_CHANGED\n");
- break;
- case BATTERY_SAVER_MODE_STATE_CHANGED:
- sb.append("BATTERY_SAVER_MODE_STATE_CHANGED\n");
- break;
- case PROCESS_LIFE_CYCLE_STATE_CHANGED:
- sb.append("PROCESS_LIFE_CYCLE_STATE_CHANGED\n");
- break;
- case ACTIVITY_FOREGROUND_STATE_CHANGED:
- sb.append("ACTIVITY_FOREGROUND_STATE_CHANGED\n");
- break;
- case BLE_UNOPTIMIZED_SCAN_STATE_CHANGED:
- sb.append("BLE_UNOPTIMIZED_SCAN_STATE_CHANGED\n");
- break;
- case LONG_PARTIAL_WAKELOCK_STATE_CHANGED:
- sb.append("LONG_PARTIAL_WAKELOCK_STATE_CHANGED\n");
- break;
- case PUSHED_NOT_SET:
- sb.append("PUSHED_NOT_SET\n");
- break;
- }
+ sb.append(event.getAtom().getPushedCase().toString()).append("\n");
}
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 7a1931718..037aeb0 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -35,23 +35,23 @@
void setServiceInfo(in AccessibilityServiceInfo info);
- boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+ String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
in Bundle arguments);
- boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
+ String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId);
- boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+ String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId);
- boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
+ String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
- boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
+ String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
diff --git a/core/java/android/annotation/IntDef.java b/core/java/android/annotation/IntDef.java
index 3f9064e..f84a676 100644
--- a/core/java/android/annotation/IntDef.java
+++ b/core/java/android/annotation/IntDef.java
@@ -52,10 +52,12 @@
@Target({ANNOTATION_TYPE})
public @interface IntDef {
/** Defines the constant prefix for this element */
- String[] prefix() default "";
+ String[] prefix() default {};
+ /** Defines the constant suffix for this element */
+ String[] suffix() default {};
/** Defines the allowed constants for this element */
- long[] value() default {};
+ int[] value() default {};
/** Defines whether the constants can be used as a flag, or just as an enum (the default) */
boolean flag() default false;
diff --git a/core/java/android/annotation/LongDef.java b/core/java/android/annotation/LongDef.java
new file mode 100644
index 0000000..8723eef8
--- /dev/null
+++ b/core/java/android/annotation/LongDef.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that the annotated long element represents
+ * a logical type and that its value should be one of the explicitly
+ * named constants. If the {@link #flag()} attribute is set to true,
+ * multiple constants can be combined.
+ * <p>
+ * <pre><code>
+ * @Retention(SOURCE)
+ * @LongDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ * public @interface NavigationMode {}
+ * public static final long NAVIGATION_MODE_STANDARD = 0;
+ * public static final long NAVIGATION_MODE_LIST = 1;
+ * public static final long NAVIGATION_MODE_TABS = 2;
+ * ...
+ * public abstract void setNavigationMode(@NavigationMode long mode);
+ * @NavigationMode
+ * public abstract long getNavigationMode();
+ * </code></pre>
+ * For a flag, set the flag attribute:
+ * <pre><code>
+ * @LongDef(
+ * flag = true,
+ * value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ * </code></pre>
+ *
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({ANNOTATION_TYPE})
+public @interface LongDef {
+ /** Defines the constant prefix for this element */
+ String[] prefix() default "";
+
+ /** Defines the allowed constants for this element */
+ long[] value() default {};
+
+ /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
+ boolean flag() default false;
+}
diff --git a/core/java/android/annotation/StringDef.java b/core/java/android/annotation/StringDef.java
index d5157c3..a37535b 100644
--- a/core/java/android/annotation/StringDef.java
+++ b/core/java/android/annotation/StringDef.java
@@ -46,6 +46,11 @@
@Retention(SOURCE)
@Target({ANNOTATION_TYPE})
public @interface StringDef {
+ /** Defines the constant prefix for this element */
+ String[] prefix() default {};
+ /** Defines the constant suffix for this element */
+ String[] suffix() default {};
+
/** Defines the allowed constants for this element */
String[] value() default {};
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9241378..142630e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2944,10 +2944,10 @@
/**
* Constant for {@link #importance}: This process is running an
* application that can not save its state, and thus can't be killed
- * while in the background.
- * @hide
+ * while in the background. This will be used with apps that have
+ * {@link android.R.attr#cantSaveState} set on their application tag.
*/
- public static final int IMPORTANCE_CANT_SAVE_STATE= 270;
+ public static final int IMPORTANCE_CANT_SAVE_STATE = 270;
/**
* Constant for {@link #importance}: This process is contains services
@@ -2995,7 +2995,7 @@
return IMPORTANCE_CACHED;
} else if (procState >= PROCESS_STATE_SERVICE) {
return IMPORTANCE_SERVICE;
- } else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
+ } else if (procState == PROCESS_STATE_HEAVY_WEIGHT) {
return IMPORTANCE_CANT_SAVE_STATE;
} else if (procState >= PROCESS_STATE_TRANSIENT_BACKGROUND) {
return IMPORTANCE_PERCEPTIBLE;
@@ -3051,7 +3051,7 @@
return PROCESS_STATE_HOME;
} else if (importance >= IMPORTANCE_SERVICE) {
return PROCESS_STATE_SERVICE;
- } else if (importance > IMPORTANCE_CANT_SAVE_STATE) {
+ } else if (importance == IMPORTANCE_CANT_SAVE_STATE) {
return PROCESS_STATE_HEAVY_WEIGHT;
} else if (importance >= IMPORTANCE_PERCEPTIBLE) {
return PROCESS_STATE_TRANSIENT_BACKGROUND;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8a4d29b..5369adf 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5605,7 +5605,16 @@
// Continue loading instrumentation.
if (ii != null) {
- final ApplicationInfo instrApp = new ApplicationInfo();
+ ApplicationInfo instrApp;
+ try {
+ instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
+ UserHandle.myUserId());
+ } catch (RemoteException e) {
+ instrApp = null;
+ }
+ if (instrApp == null) {
+ instrApp = new ApplicationInfo();
+ }
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 55f9e28..382719b 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -568,9 +568,21 @@
}
/**
- * Schedule an alarm that represents an alarm clock.
+ * Schedule an alarm that represents an alarm clock, which will be used to notify the user
+ * when it goes off. The expectation is that when this alarm triggers, the application will
+ * further wake up the device to tell the user about the alarm -- turning on the screen,
+ * playing a sound, vibrating, etc. As such, the system will typically also use the
+ * information supplied here to tell the user about this upcoming alarm if appropriate.
*
- * The system may choose to display information about this alarm to the user.
+ * <p>Due to the nature of this kind of alarm, similar to {@link #setExactAndAllowWhileIdle},
+ * these alarms will be allowed to trigger even if the system is in a low-power idle
+ * (a.k.a. doze) mode. The system may also do some prep-work when it sees that such an
+ * alarm coming up, to reduce the amount of background work that could happen if this
+ * causes the device to fully wake up -- this is to avoid situations such as a large number
+ * of devices having an alarm set at the same time in the morning, all waking up at that
+ * time and suddenly swamping the network with pending background work. As such, these
+ * types of alarms can be extremely expensive on battery use and should only be used for
+ * their intended purpose.</p>
*
* <p>
* This method is like {@link #setExact(int, long, PendingIntent)}, but implies
@@ -783,9 +795,9 @@
/**
* Like {@link #set(int, long, PendingIntent)}, but this alarm will be allowed to execute
- * even when the system is in low-power idle modes. This type of alarm must <b>only</b>
- * be used for situations where it is actually required that the alarm go off while in
- * idle -- a reasonable example would be for a calendar notification that should make a
+ * even when the system is in low-power idle (a.k.a. doze) modes. This type of alarm must
+ * <b>only</b> be used for situations where it is actually required that the alarm go off while
+ * in idle -- a reasonable example would be for a calendar notification that should make a
* sound so the user is aware of it. When the alarm is dispatched, the app will also be
* added to the system's temporary whitelist for approximately 10 seconds to allow that
* application to acquire further wake locks in which to complete its work.</p>
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f831ae2..495fd3c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -618,12 +618,13 @@
ConnectivityThread.getInstanceLooper());
}});
- registerService(Context.WIFI_RTT2_SERVICE, WifiRttManager.class,
+ registerService(Context.WIFI_RTT_RANGING_SERVICE, WifiRttManager.class,
new CachedServiceFetcher<WifiRttManager>() {
@Override
public WifiRttManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT2_SERVICE);
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.WIFI_RTT_RANGING_SERVICE);
IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
return new WifiRttManager(ctx.getOuterContext(), service);
}});
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 562b981..ad21983 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8585,32 +8585,31 @@
}
/**
- * Called by a device owner to specify whether a logout button is enabled for all secondary
- * users. The system may show a logout button that stops the user and switches back to the
- * primary user.
+ * Called by a device owner to specify whether logout is enabled for all secondary users. The
+ * system may show a logout button that stops the user and switches back to the primary user.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param enabled whether logout button should be enabled or not.
+ * @param enabled whether logout should be enabled or not.
* @throws SecurityException if {@code admin} is not a device owner.
*/
- public void setLogoutButtonEnabled(@NonNull ComponentName admin, boolean enabled) {
- throwIfParentInstance("setLogoutButtonEnabled");
+ public void setLogoutEnabled(@NonNull ComponentName admin, boolean enabled) {
+ throwIfParentInstance("setLogoutEnabled");
try {
- mService.setLogoutButtonEnabled(admin, enabled);
+ mService.setLogoutEnabled(admin, enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
- * Returns whether logout button is enabled by a device owner.
+ * Returns whether logout is enabled by a device owner.
*
- * @return {@code true} if logout button is enabled by device owner, {@code false} otherwise.
+ * @return {@code true} if logout is enabled by device owner, {@code false} otherwise.
*/
- public boolean isLogoutButtonEnabled() {
- throwIfParentInstance("isLogoutButtonEnabled");
+ public boolean isLogoutEnabled() {
+ throwIfParentInstance("isLogoutEnabled");
try {
- return mService.isLogoutButtonEnabled();
+ return mService.isLogoutEnabled();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c525df7..ff869d2 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -372,6 +372,6 @@
boolean clearApplicationUserData(in ComponentName admin, in String packageName, in IPackageDataObserver callback);
- void setLogoutButtonEnabled(in ComponentName admin, boolean enabled);
- boolean isLogoutButtonEnabled();
+ void setLogoutEnabled(in ComponentName admin, boolean enabled);
+ boolean isLogoutEnabled();
}
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index ddc5760..807c47d 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -37,6 +37,8 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -53,9 +55,21 @@
/**
* @hide
*/
- @StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED,
- HINT_NO_TINT, HINT_PARTIAL})
- public @interface SliceHint{ }
+ @StringDef(prefix = { "HINT_" }, value = {
+ HINT_TITLE,
+ HINT_LIST,
+ HINT_LIST_ITEM,
+ HINT_LARGE,
+ HINT_ACTIONS,
+ HINT_SELECTED,
+ HINT_NO_TINT,
+ HINT_HIDDEN,
+ HINT_TOGGLE,
+ HINT_HORIZONTAL,
+ HINT_PARTIAL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SliceHint {}
/**
* The meta-data key that allows an activity to easily be linked directly to a slice.
diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
index cdeee35..743d6b7 100644
--- a/core/java/android/app/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -29,6 +29,8 @@
import com.android.internal.util.ArrayUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
@@ -55,8 +57,16 @@
/**
* @hide
*/
- @StringDef({FORMAT_SLICE, FORMAT_TEXT, FORMAT_IMAGE, FORMAT_ACTION, FORMAT_COLOR,
- FORMAT_TIMESTAMP, FORMAT_REMOTE_INPUT})
+ @StringDef(prefix = { "FORMAT_" }, value = {
+ FORMAT_SLICE,
+ FORMAT_TEXT,
+ FORMAT_IMAGE,
+ FORMAT_ACTION,
+ FORMAT_COLOR,
+ FORMAT_TIMESTAMP,
+ FORMAT_REMOTE_INPUT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
public @interface SliceType {}
/**
diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java
index ad9b698..417e7d2 100644
--- a/core/java/android/app/timezone/RulesManager.java
+++ b/core/java/android/app/timezone/RulesManager.java
@@ -105,9 +105,9 @@
*/
public RulesState getRulesState() {
try {
- logDebug("sIRulesManager.getRulesState()");
+ logDebug("mIRulesManager.getRulesState()");
RulesState rulesState = mIRulesManager.getRulesState();
- logDebug("sIRulesManager.getRulesState() returned " + rulesState);
+ logDebug("mIRulesManager.getRulesState() returned " + rulesState);
return rulesState;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -131,7 +131,7 @@
ICallback iCallback = new CallbackWrapper(mContext, callback);
try {
- logDebug("sIRulesManager.requestInstall()");
+ logDebug("mIRulesManager.requestInstall()");
return mIRulesManager.requestInstall(distroFileDescriptor, checkToken, iCallback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -151,7 +151,7 @@
public int requestUninstall(byte[] checkToken, Callback callback) {
ICallback iCallback = new CallbackWrapper(mContext, callback);
try {
- logDebug("sIRulesManager.requestUninstall()");
+ logDebug("mIRulesManager.requestUninstall()");
return mIRulesManager.requestUninstall(checkToken, iCallback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -196,7 +196,7 @@
*/
public void requestNothing(byte[] checkToken, boolean succeeded) {
try {
- logDebug("sIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken));
+ logDebug("mIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken));
mIRulesManager.requestNothing(checkToken, succeeded);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java
new file mode 100644
index 0000000..7ab3d8b
--- /dev/null
+++ b/core/java/android/appwidget/AppWidgetManagerInternal.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appwidget;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArraySet;
+
+import java.util.Set;
+
+/**
+ * App widget manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class AppWidgetManagerInternal {
+
+ /**
+ * Gets the packages from which the uid hosts widgets.
+ *
+ * @param uid The potential host UID.
+ * @return Whether the UID hosts widgets from the package.
+ */
+ public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid);
+}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
index 55c3a73..73a2e74 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
@@ -71,7 +71,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mSyncHandle);
- dest.writeLong(mTxPower);
+ dest.writeInt(mTxPower);
dest.writeInt(mRssi);
dest.writeInt(mDataStatus);
if (mData != null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9800ab00..a474330 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2913,7 +2913,7 @@
@Nullable String profileFile, @Nullable Bundle arguments);
/** @hide */
- @StringDef({
+ @StringDef(suffix = { "_SERVICE" }, value = {
POWER_SERVICE,
WINDOW_SERVICE,
LAYOUT_INFLATER_SERVICE,
@@ -2947,7 +2947,7 @@
//@hide: LOWPAN_SERVICE,
//@hide: WIFI_RTT_SERVICE,
//@hide: ETHERNET_SERVICE,
- WIFI_RTT_SERVICE,
+ WIFI_RTT_RANGING_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
FINGERPRINT_SERVICE,
@@ -3496,7 +3496,7 @@
* @see android.net.wifi.rtt.WifiRttManager
* @hide
*/
- public static final String WIFI_RTT2_SERVICE = "rttmanager2";
+ public static final String WIFI_RTT_RANGING_SERVICE = "rttmanager2";
/**
* Use with {@link #getSystemService} to retrieve a {@link
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 551d53b..21bd7f0 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -150,6 +151,7 @@
*
* @hide
*/
+ @TestApi
public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000;
/**
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index 7049628..b111ad3 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -17,6 +17,7 @@
package android.hardware;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -70,7 +71,7 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
+ @LongDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE,
USAGE_GPU_COLOR_OUTPUT, USAGE_PROTECTED_CONTENT, USAGE_VIDEO_ENCODE,
USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA})
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 223ed73..02b1c65 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -392,7 +392,7 @@
mWindow.setToken(token);
}
}
-
+
/**
* {@inheritDoc}
*
@@ -1064,7 +1064,89 @@
}
return mInputConnection;
}
-
+
+ /**
+ * Force switch to a new input method component. This can only be called
+ * from an application or a service which has a token of the currently active input method.
+ * @param id The unique identifier for the new input method to be switched to.
+ */
+ public void setInputMethod(String id) {
+ mImm.setInputMethodInternal(mToken, id);
+ }
+
+ /**
+ * Force switch to a new input method and subtype. This can only be called
+ * from an application or a service which has a token of the currently active input method.
+ * @param id The unique identifier for the new input method to be switched to.
+ * @param subtype The new subtype of the new input method to be switched to.
+ */
+ public void setInputMethodAndSubtype(String id, InputMethodSubtype subtype) {
+ mImm.setInputMethodAndSubtypeInternal(mToken, id, subtype);
+ }
+
+ /**
+ * Close/hide the input method's soft input area, so the user no longer
+ * sees it or can interact with it. This can only be called
+ * from the currently active input method, as validated by the given token.
+ *
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY},
+ * {@link InputMethodManager#HIDE_NOT_ALWAYS} bit set.
+ */
+ public void hideSoftInputFromInputMethod(int flags) {
+ mImm.hideSoftInputFromInputMethodInternal(mToken, flags);
+ }
+
+ /**
+ * Show the input method's soft input area, so the user
+ * sees the input method window and can interact with it.
+ * This can only be called from the currently active input method,
+ * as validated by the given token.
+ *
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link InputMethodManager#SHOW_IMPLICIT} or
+ * {@link InputMethodManager#SHOW_FORCED} bit set.
+ */
+ public void showSoftInputFromInputMethod(int flags) {
+ mImm.showSoftInputFromInputMethodInternal(mToken, flags);
+ }
+
+ /**
+ * Force switch to the last used input method and subtype. If the last input method didn't have
+ * any subtypes, the framework will simply switch to the last input method with no subtype
+ * specified.
+ * @return true if the current input method and subtype was successfully switched to the last
+ * used input method and subtype.
+ */
+ public boolean switchToLastInputMethod() {
+ return mImm.switchToLastInputMethodInternal(mToken);
+ }
+
+ /**
+ * Force switch to the next input method and subtype. If there is no IME enabled except
+ * current IME and subtype, do nothing.
+ * @param onlyCurrentIme if true, the framework will find the next subtype which
+ * belongs to the current IME
+ * @return true if the current input method and subtype was successfully switched to the next
+ * input method and subtype.
+ */
+ public boolean switchToNextInputMethod(boolean onlyCurrentIme) {
+ return mImm.switchToNextInputMethodInternal(mToken, onlyCurrentIme);
+ }
+
+ /**
+ * Returns true if the current IME needs to offer the users ways to switch to a next input
+ * method (e.g. a globe key.).
+ * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
+ * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
+ * <p> Note that the system determines the most appropriate next input method
+ * and subtype in order to provide the consistent user experience in switching
+ * between IMEs and subtypes.
+ */
+ public boolean shouldOfferSwitchingToNextInputMethod() {
+ return mImm.shouldOfferSwitchingToNextInputMethodInternal(mToken);
+ }
+
public boolean getCurrentInputStarted() {
return mInputStarted;
}
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 8ff8e4f..6f383b4 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -74,7 +74,7 @@
j.add("final_score=" + finalScore);
}
j.add(String.format("duration=%.0fs", durationMs / 1000.0));
- j.add(String.format("validation=%4.1f%%", (validatedMs * 100.0) / durationMs));
+ j.add(String.format("validation=%04.1f%%", (validatedMs * 100.0) / durationMs));
return j.toString();
}
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyGenerator.java b/core/java/android/security/recoverablekeystore/RecoverableKeyGenerator.java
new file mode 100644
index 0000000..4125f0ba
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyGenerator.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.recoverablekeystore;
+
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
+import android.util.Log;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.security.auth.DestroyFailedException;
+
+/**
+ * Generates keys and stores them both in AndroidKeyStore and on disk, in wrapped form.
+ *
+ * <p>Generates 256-bit AES keys, which can be used for encrypt / decrypt with AES/GCM/NoPadding.
+ * They are synced to disk wrapped by a platform key. This allows them to be exported to a remote
+ * service.
+ *
+ * @hide
+ */
+public class RecoverableKeyGenerator {
+ private static final String TAG = "RecoverableKeyGenerator";
+ private static final String KEY_GENERATOR_ALGORITHM = "AES";
+ private static final int KEY_SIZE_BITS = 256;
+
+ /**
+ * A new {@link RecoverableKeyGenerator} instance.
+ *
+ * @param platformKey Secret key used to wrap generated keys before persisting to disk.
+ * @param recoverableKeyStorage Class that manages persisting wrapped keys to disk.
+ * @throws NoSuchAlgorithmException if "AES" key generation or "AES/GCM/NoPadding" cipher is
+ * unavailable. Should never happen.
+ *
+ * @hide
+ */
+ public static RecoverableKeyGenerator newInstance(
+ AndroidKeyStoreSecretKey platformKey, RecoverableKeyStorage recoverableKeyStorage)
+ throws NoSuchAlgorithmException {
+ // NB: This cannot use AndroidKeyStore as the provider, as we need access to the raw key
+ // material, so that it can be synced to disk in encrypted form.
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_GENERATOR_ALGORITHM);
+ return new RecoverableKeyGenerator(keyGenerator, platformKey, recoverableKeyStorage);
+ }
+
+ private final KeyGenerator mKeyGenerator;
+ private final RecoverableKeyStorage mRecoverableKeyStorage;
+ private final AndroidKeyStoreSecretKey mPlatformKey;
+
+ private RecoverableKeyGenerator(
+ KeyGenerator keyGenerator,
+ AndroidKeyStoreSecretKey platformKey,
+ RecoverableKeyStorage recoverableKeyStorage) {
+ mKeyGenerator = keyGenerator;
+ mRecoverableKeyStorage = recoverableKeyStorage;
+ mPlatformKey = platformKey;
+ }
+
+ /**
+ * Generates a 256-bit AES key with the given alias.
+ *
+ * <p>Stores in the AndroidKeyStore, as well as persisting in wrapped form to disk. It is
+ * persisted to disk so that it can be synced remotely, and then recovered on another device.
+ * The generated key allows encrypt/decrypt only using AES/GCM/NoPadding.
+ *
+ * <p>The key handle returned to the caller is a reference to the AndroidKeyStore key,
+ * meaning that the caller is never able to access the raw, unencrypted key.
+ *
+ * @param alias The alias by which the key will be known in AndroidKeyStore.
+ * @throws InvalidKeyException if the platform key cannot be used to wrap keys.
+ * @throws IOException if there was an issue writing the wrapped key to the wrapped key store.
+ * @throws UnrecoverableEntryException if could not retrieve key after putting it in
+ * AndroidKeyStore. This should not happen.
+ * @return A handle to the AndroidKeyStore key.
+ *
+ * @hide
+ */
+ public SecretKey generateAndStoreKey(String alias) throws KeyStoreException,
+ InvalidKeyException, IOException, UnrecoverableEntryException {
+ mKeyGenerator.init(KEY_SIZE_BITS);
+ SecretKey key = mKeyGenerator.generateKey();
+
+ mRecoverableKeyStorage.importIntoAndroidKeyStore(
+ alias,
+ key,
+ new KeyProtection.Builder(
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ WrappedKey wrappedKey = WrappedKey.fromSecretKey(mPlatformKey, key);
+
+ try {
+ // Keep raw key material in memory for minimum possible time.
+ key.destroy();
+ } catch (DestroyFailedException e) {
+ Log.w(TAG, "Could not destroy SecretKey.");
+ }
+
+ mRecoverableKeyStorage.persistToDisk(alias, wrappedKey);
+
+ try {
+ // Reload from the keystore, so that the caller is only provided with the handle of the
+ // key, not the raw key material.
+ return mRecoverableKeyStorage.loadFromAndroidKeyStore(alias);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(
+ "Impossible: NoSuchAlgorithmException when attempting to retrieve a key "
+ + "that has only just been stored in AndroidKeyStore.", e);
+ }
+ }
+}
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyStorage.java b/core/java/android/security/recoverablekeystore/RecoverableKeyStorage.java
new file mode 100644
index 0000000..c239e00
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyStorage.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.recoverablekeystore;
+
+import android.security.keystore.KeyProtection;
+
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Stores wrapped keys to disk, so they can be synced on the next screen unlock event.
+ *
+ * @hide
+ */
+public interface RecoverableKeyStorage {
+
+ /**
+ * Writes {@code wrappedKey} to disk, keyed by the application's uid and the {@code alias}.
+ *
+ * @throws IOException if an error occurred writing to disk.
+ *
+ * @hide
+ */
+ void persistToDisk(String alias, WrappedKey wrappedKey) throws IOException;
+
+ /**
+ * Imports {@code key} into AndroidKeyStore, keyed by the application's uid and
+ * the {@code alias}.
+ *
+ * @param alias The alias of the key.
+ * @param key The key.
+ * @param keyProtection Protection params denoting what the key can be used for. (e.g., what
+ * Cipher modes, whether for encrpyt/decrypt or signing, etc.)
+ * @throws KeyStoreException if an error occurred loading the key into the AndroidKeyStore.
+ *
+ * @hide
+ */
+ void importIntoAndroidKeyStore(String alias, SecretKey key, KeyProtection keyProtection) throws
+ KeyStoreException;
+
+ /**
+ * Loads a key handle from AndroidKeyStore.
+ *
+ * @param alias Alias of the key to load.
+ * @return The key handle.
+ * @throws KeyStoreException if an error occurred loading the key from AndroidKeyStore.
+ *
+ * @hide
+ */
+ SecretKey loadFromAndroidKeyStore(String alias) throws KeyStoreException,
+ NoSuchAlgorithmException,
+ UnrecoverableEntryException;
+}
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyStorageImpl.java b/core/java/android/security/recoverablekeystore/RecoverableKeyStorageImpl.java
new file mode 100644
index 0000000..b9926dd
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyStorageImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.recoverablekeystore;
+
+import android.security.keystore.KeyProtection;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+import java.security.cert.CertificateException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Implementation of {@link RecoverableKeyStorage}.
+ *
+ * <p>Persists wrapped keys to disk, and loads raw keys into AndroidKeyStore.
+ *
+ * @hide
+ */
+public class RecoverableKeyStorageImpl implements RecoverableKeyStorage {
+ private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+
+ private final KeyStore mKeyStore;
+
+ /**
+ * A new instance.
+ *
+ * @throws KeyStoreException if unable to load AndroidKeyStore.
+ *
+ * @hide
+ */
+ public static RecoverableKeyStorageImpl newInstance() throws KeyStoreException {
+ KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+ try {
+ keyStore.load(/*param=*/ null);
+ } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
+ // Should never happen.
+ throw new KeyStoreException("Unable to load keystore.", e);
+ }
+ return new RecoverableKeyStorageImpl(keyStore);
+ }
+
+ private RecoverableKeyStorageImpl(KeyStore keyStore) {
+ mKeyStore = keyStore;
+ }
+
+ /**
+ * Writes {@code wrappedKey} to disk, keyed by the application's uid and the {@code alias}.
+ *
+ * @throws IOException if an error occurred writing to disk.
+ *
+ * @hide
+ */
+ @Override
+ public void persistToDisk(String alias, WrappedKey wrappedKey) throws IOException {
+ // TODO(robertberry) Add implementation.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Imports {@code key} into AndroidKeyStore, keyed by the application's uid and the
+ * {@code alias}.
+ *
+ * @param alias The alias of the key.
+ * @param key The key.
+ * @param keyProtection Protection params denoting what the key can be used for. (e.g., what
+ * Cipher modes, whether for encrpyt/decrypt or signing, etc.)
+ * @throws KeyStoreException if an error occurred loading the key into the AndroidKeyStore.
+ *
+ * @hide
+ */
+ @Override
+ public void importIntoAndroidKeyStore(String alias, SecretKey key, KeyProtection keyProtection)
+ throws KeyStoreException {
+ mKeyStore.setEntry(alias, new KeyStore.SecretKeyEntry(key), keyProtection);
+ }
+
+ /**
+ * Loads a key handle from AndroidKeyStore.
+ *
+ * @param alias Alias of the key to load.
+ * @return The key handle.
+ * @throws KeyStoreException if an error occurred loading the key from AndroidKeyStore.
+ *
+ * @hide
+ */
+ @Override
+ public SecretKey loadFromAndroidKeyStore(String alias)
+ throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
+ return ((KeyStore.SecretKeyEntry) mKeyStore.getEntry(alias, /*protParam=*/ null))
+ .getSecretKey();
+ }
+}
diff --git a/core/java/android/security/recoverablekeystore/WrappedKey.java b/core/java/android/security/recoverablekeystore/WrappedKey.java
new file mode 100644
index 0000000..51665ae
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/WrappedKey.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.recoverablekeystore;
+
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+/**
+ * A {@link javax.crypto.SecretKey} wrapped with AES/GCM/NoPadding.
+ *
+ * @hide
+ */
+public class WrappedKey {
+ private static final String KEY_WRAP_CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+ private final byte[] mNonce;
+ private final byte[] mKeyMaterial;
+
+ /**
+ * Returns a wrapped form of {@code key}, using {@code wrappingKey} to encrypt the key material.
+ *
+ * @throws InvalidKeyException if {@code wrappingKey} cannot be used to encrypt {@code key}, or
+ * if {@code key} does not expose its key material. See
+ * {@link android.security.keystore.AndroidKeyStoreKey} for an example of a key that does
+ * not expose its key material.
+ */
+ public static WrappedKey fromSecretKey(
+ SecretKey wrappingKey, SecretKey key) throws InvalidKeyException, KeyStoreException {
+ if (key.getEncoded() == null) {
+ throw new InvalidKeyException(
+ "key does not expose encoded material. It cannot be wrapped.");
+ }
+
+ Cipher cipher;
+ try {
+ cipher = Cipher.getInstance(KEY_WRAP_CIPHER_ALGORITHM);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new RuntimeException(
+ "Android does not support AES/GCM/NoPadding. This should never happen.");
+ }
+
+ cipher.init(Cipher.WRAP_MODE, wrappingKey);
+ byte[] encryptedKeyMaterial;
+ try {
+ encryptedKeyMaterial = cipher.wrap(key);
+ } catch (IllegalBlockSizeException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof KeyStoreException) {
+ // If AndroidKeyStore encounters any error here, it throws IllegalBlockSizeException
+ // with KeyStoreException as the cause. This is due to there being no better option
+ // here, as the Cipher#wrap only checked throws InvalidKeyException or
+ // IllegalBlockSizeException. If this is the case, we want to propagate it to the
+ // caller, so rethrow the cause.
+ throw (KeyStoreException) cause;
+ } else {
+ throw new RuntimeException(
+ "IllegalBlockSizeException should not be thrown by AES/GCM/NoPadding mode.",
+ e);
+ }
+ }
+
+ return new WrappedKey(/*mNonce=*/ cipher.getIV(), /*mKeyMaterial=*/ encryptedKeyMaterial);
+ }
+
+ /**
+ * A new instance.
+ *
+ * @param nonce The nonce with which the key material was encrypted.
+ * @param keyMaterial The encrypted bytes of the key material.
+ *
+ * @hide
+ */
+ public WrappedKey(byte[] nonce, byte[] keyMaterial) {
+ mNonce = nonce;
+ mKeyMaterial = keyMaterial;
+ }
+
+ /**
+ * Returns the nonce with which the key material was encrypted.
+ *
+ * @hide
+ */
+ public byte[] getNonce() {
+ return mNonce;
+ }
+
+ /**
+ * Returns the encrypted key material.
+ *
+ * @hide
+ */
+ public byte[] getKeyMaterial() {
+ return mKeyMaterial;
+ }
+}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 1afa8b3..97fdcef 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -445,7 +445,7 @@
*
* <p>The {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} method is called
* without the user content. The Android system strips some properties of the
- * {@link android.app.assist.AssistStructure.ViewNode view nodes} passed to these calls, but not all
+ * {@link android.app.assist.AssistStructure.ViewNode view nodes} passed to this call, but not all
* of them. For example, the data provided in the {@link android.view.ViewStructure.HtmlInfo}
* objects set by {@link android.webkit.WebView} is never stripped out.
*
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 3a84224..ddc92f6 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -127,12 +127,15 @@
}
/**
- * Gets the extra client state returned from the last {@link
- * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)
- * fill request}, so the service can use it for state management.
+ * Gets the latest client state bundle set by the service in a
+ * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
*
- * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
- * save request} is made, the client state is cleared.
+ * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
+ * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
+ * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
+ * an authenticated request through the
+ * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
+ * also considered (and take precedence when set).
*
* @return The client state.
*/
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 06d2b07..04db698 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -49,14 +49,16 @@
public final class FillResponse implements Parcelable {
/**
- * Must be set in the last response to generate
- * {@link FillEventHistory.Event#TYPE_CONTEXT_COMMITTED} events.
+ * Flag used to generate {@link FillEventHistory.Event events} of type
+ * {@link FillEventHistory.Event#TYPE_CONTEXT_COMMITTED}—if this flag is not passed to
+ * {@link Builder#setFlags(int)}, these events are not generated.
*/
public static final int FLAG_TRACK_CONTEXT_COMMITED = 0x1;
/**
- * Used in conjunction to {@link FillResponse.Builder#disableAutofill(long)} to disable autofill
- * only for the activiy associated with the {@link FillResponse}, instead of the whole app.
+ * Flag used to change the behavior of {@link FillResponse.Builder#disableAutofill(long)}—
+ * when this flag is passed to {@link Builder#setFlags(int)}, autofill is disabled only for the
+ * activiy that generated the {@link FillRequest}, not the whole app.
*/
public static final int FLAG_DISABLE_ACTIVITY_ONLY = 0x2;
@@ -329,19 +331,16 @@
}
/**
- * Sets a {@link Bundle state} that will be passed to subsequent APIs that
- * manipulate this response. For example, they are passed to subsequent
- * calls to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
- * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}.
- * You can use this to store intermediate state that is persistent across multiple
- * fill requests and the subsequent save request.
+ * Sets a bundle with state that is passed to subsequent APIs that manipulate this response.
+ *
+ * <p>You can use this bundle to store intermediate state that is passed to subsequent calls
+ * to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+ * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}, and
+ * you can also retrieve it by calling {@link FillEventHistory.Event#getClientState()}.
*
* <p>If this method is called on multiple {@link FillResponse} objects for the same
* screen, just the latest bundle is passed back to the service.
*
- * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
- * save request} is made the client state is cleared.
- *
* @param clientState The custom client state.
* @return This builder.
*/
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
index f53967b..4f85e6b 100644
--- a/core/java/android/service/autofill/SaveRequest.java
+++ b/core/java/android/service/autofill/SaveRequest.java
@@ -59,10 +59,11 @@
}
/**
- * Gets the latest client state extra returned from the service.
+ * Gets the latest client state bundle set by the service in a
+ * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
*
* <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
- * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} where considered. On
+ * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
* Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
* an authenticated request through the
* {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
diff --git a/core/java/android/service/autofill/Validators.java b/core/java/android/service/autofill/Validators.java
index 1c83868..0f1ba98 100644
--- a/core/java/android/service/autofill/Validators.java
+++ b/core/java/android/service/autofill/Validators.java
@@ -33,6 +33,8 @@
/**
* Creates a validator that is only valid if all {@code validators} are valid.
*
+ * <p>Used to represent an {@code AND} boolean operation in a chain of validators.
+ *
* @throws IllegalArgumentException if any element of {@code validators} is an instance of a
* class that is not provided by the Android System.
*/
@@ -44,6 +46,8 @@
/**
* Creates a validator that is valid if any of the {@code validators} is valid.
*
+ * <p>Used to represent an {@code OR} boolean operation in a chain of validators.
+ *
* @throws IllegalArgumentException if any element of {@code validators} is an instance of a
* class that is not provided by the Android System.
*/
@@ -53,7 +57,9 @@
}
/**
- * Creates a validator that is valid only if {@code validator} is not.
+ * Creates a validator that is valid when {@code validator} is not, and vice versa.
+ *
+ * <p>Used to represent a {@code NOT} boolean operation in a chain of validators.
*
* @throws IllegalArgumentException if {@code validator} is an instance of a class that is not
* provided by the Android System.
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 80785fd..54b48b6 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -43,6 +43,7 @@
DEFAULT_FLAGS.put("settings_app_info_v2", "false");
DEFAULT_FLAGS.put("settings_connected_device_v2", "false");
DEFAULT_FLAGS.put("settings_battery_v2", "false");
+ DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
}
/**
diff --git a/core/java/android/view/FrameInfo.java b/core/java/android/view/FrameInfo.java
index c79547c..6c5e048 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/core/java/android/view/FrameInfo.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.IntDef;
+import android.annotation.LongDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -48,7 +48,7 @@
// Is this the first-draw following a window layout?
public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
- @IntDef(flag = true, value = {
+ @LongDef(flag = true, value = {
FLAG_WINDOW_LAYOUT_CHANGED })
@Retention(RetentionPolicy.SOURCE)
public @interface FrameInfoFlags {}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 420a1bb..8a7b441 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -18,11 +18,18 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+import static android.graphics.Matrix.MSKEW_X;
+import static android.graphics.Matrix.MSKEW_Y;
+import static android.graphics.Matrix.MTRANS_X;
+import static android.graphics.Matrix.MTRANS_Y;
import android.annotation.Size;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
+import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
@@ -862,6 +869,22 @@
}
}
+ /**
+ * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation matrix.
+ *
+ * @param matrix The matrix to apply.
+ * @param float9 An array of 9 floats to be used to extract the values from the matrix.
+ */
+ public void setMatrix(Matrix matrix, float[] float9) {
+ checkNotReleased();
+ matrix.getValues(float9);
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setMatrix(this, float9[MSCALE_X], float9[MSKEW_Y],
+ float9[MSKEW_X], float9[MSCALE_Y]);
+ sGlobalTransaction.setPosition(this, float9[MTRANS_X], float9[MTRANS_Y]);
+ }
+ }
+
public void setWindowCrop(Rect crop) {
checkNotReleased();
synchronized (SurfaceControl.class) {
@@ -1348,6 +1371,14 @@
return this;
}
+ public Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
+ matrix.getValues(float9);
+ setMatrix(sc, float9[MSCALE_X], float9[MSKEW_Y],
+ float9[MSKEW_X], float9[MSCALE_Y]);
+ setPosition(sc, float9[MTRANS_X], float9[MTRANS_Y]);
+ return this;
+ }
+
public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
sc.checkNotReleased();
if (crop != null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0bae36bf4..6d4998b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -7907,6 +7907,7 @@
if (!registered) {
mAttachInfo.mAccessibilityWindowId =
mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
+ mContext.getPackageName(),
new AccessibilityInteractionConnection(ViewRootImpl.this));
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 7c2c12f..500701d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -20,6 +20,7 @@
import android.Manifest.permission;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
@@ -1270,7 +1271,7 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(
+ @LongDef(
flag = true,
value = {
LayoutParams.FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA,
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index d890f32..e146555 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -29,6 +29,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -213,7 +214,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @return The {@link AccessibilityWindowInfo}.
*/
@@ -299,7 +300,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
@@ -335,18 +336,19 @@
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
- final boolean success;
+ final String[] packageNames;
try {
- success = connection.findAccessibilityNodeInfoByAccessibilityId(
+ packageNames = connection.findAccessibilityNodeInfoByAccessibilityId(
accessibilityWindowId, accessibilityNodeId, interactionId, this,
prefetchFlags, Thread.currentThread().getId(), arguments);
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- if (success) {
+ if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, bypassCache);
+ finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
+ bypassCache, packageNames);
if (infos != null && !infos.isEmpty()) {
for (int i = 1; i < infos.size(); i++) {
infos.get(i).recycle();
@@ -373,7 +375,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
@@ -389,20 +391,21 @@
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
- final boolean success;
+ final String[] packageNames;
try {
- success = connection.findAccessibilityNodeInfosByViewId(
+ packageNames = connection.findAccessibilityNodeInfosByViewId(
accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- if (success) {
+ if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (infos != null) {
- finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, false);
+ finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
+ false, packageNames);
return infos;
}
}
@@ -426,7 +429,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
@@ -442,20 +445,21 @@
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
- final boolean success;
+ final String[] packageNames;
try {
- success = connection.findAccessibilityNodeInfosByText(
+ packageNames = connection.findAccessibilityNodeInfosByText(
accessibilityWindowId, accessibilityNodeId, text, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- if (success) {
+ if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (infos != null) {
- finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, false);
+ finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
+ false, packageNames);
return infos;
}
}
@@ -478,7 +482,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
@@ -494,19 +498,19 @@
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
- final boolean success;
+ final String[] packageNames;
try {
- success = connection.findFocus(accessibilityWindowId,
+ packageNames = connection.findFocus(accessibilityWindowId,
accessibilityNodeId, focusType, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- if (success) {
+ if (packageNames != null) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
return info;
}
} else {
@@ -527,7 +531,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
@@ -543,19 +547,19 @@
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
- final boolean success;
+ final String[] packageNames;
try {
- success = connection.focusSearch(accessibilityWindowId,
+ packageNames = connection.focusSearch(accessibilityWindowId,
accessibilityNodeId, direction, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- if (success) {
+ if (packageNames != null) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
return info;
}
} else {
@@ -574,7 +578,7 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
* to query the currently active window.
* @param accessibilityNodeId A unique view id or virtual descendant id from
* where to start the search. Use
@@ -661,7 +665,7 @@
int interactionId) {
synchronized (mInstanceLock) {
final boolean success = waitForResultTimedLocked(interactionId);
- List<AccessibilityNodeInfo> result = null;
+ final List<AccessibilityNodeInfo> result;
if (success) {
result = mFindAccessibilityNodeInfosResult;
} else {
@@ -779,11 +783,19 @@
* @param connectionId The id of the connection to the system.
* @param bypassCache Whether or not to bypass the cache. The node is added to the cache if
* this value is {@code false}
+ * @param packageNames The valid package names a node can come from.
*/
private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info,
- int connectionId, boolean bypassCache) {
+ int connectionId, boolean bypassCache, String[] packageNames) {
if (info != null) {
info.setConnectionId(connectionId);
+ // Empty array means any package name is Okay
+ if (!ArrayUtils.isEmpty(packageNames)
+ && !ArrayUtils.contains(packageNames, info.getPackageName().toString())) {
+ // If the node package not one of the valid ones, pick the top one - this
+ // is one of the packages running in the introspected UID.
+ info.setPackageName(packageNames[0]);
+ }
info.setSealed(true);
if (!bypassCache) {
sAccessibilityCache.add(info);
@@ -798,14 +810,16 @@
* @param connectionId The id of the connection to the system.
* @param bypassCache Whether or not to bypass the cache. The nodes are added to the cache if
* this value is {@code false}
+ * @param packageNames The valid package names a node can come from.
*/
private void finalizeAndCacheAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
- int connectionId, boolean bypassCache) {
+ int connectionId, boolean bypassCache, String[] packageNames) {
if (infos != null) {
final int infosCount = infos.size();
for (int i = 0; i < infosCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, bypassCache);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId,
+ bypassCache, packageNames);
}
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 35f6acb..b4499d1 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -888,7 +888,7 @@
* @hide
*/
public int addAccessibilityInteractionConnection(IWindow windowToken,
- IAccessibilityInteractionConnection connection) {
+ String packageName, IAccessibilityInteractionConnection connection) {
final IAccessibilityManager service;
final int userId;
synchronized (mLock) {
@@ -899,7 +899,8 @@
userId = mUserId;
}
try {
- return service.addAccessibilityInteractionConnection(windowToken, connection, userId);
+ return service.addAccessibilityInteractionConnection(windowToken, connection,
+ packageName, userId);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index faea920..9c2f6bb 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3695,8 +3695,9 @@
if (DEBUG) {
builder.append("; sourceNodeId: " + mSourceNodeId);
- builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
- builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
+ builder.append("; windowId: " + mWindowId);
+ builder.append("; accessibilityViewId: ").append(getAccessibilityViewId(mSourceNodeId));
+ builder.append("; virtualDescendantId: ").append(getVirtualDescendantId(mSourceNodeId));
builder.append("; mParentNodeId: " + mParentNodeId);
builder.append("; traversalBefore: ").append(mTraversalBefore);
builder.append("; traversalAfter: ").append(mTraversalAfter);
@@ -3726,8 +3727,8 @@
builder.append("]");
}
- builder.append("; boundsInParent: " + mBoundsInParent);
- builder.append("; boundsInScreen: " + mBoundsInScreen);
+ builder.append("; boundsInParent: ").append(mBoundsInParent);
+ builder.append("; boundsInScreen: ").append(mBoundsInScreen);
builder.append("; packageName: ").append(mPackageName);
builder.append("; className: ").append(mClassName);
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 3f499ab..c93e2c1 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -45,7 +45,8 @@
List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
int addAccessibilityInteractionConnection(IWindow windowToken,
- in IAccessibilityInteractionConnection connection, int userId);
+ in IAccessibilityInteractionConnection connection,
+ String packageName, int userId);
void removeAccessibilityInteractionConnection(IWindow windowToken);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4d96733..3cd8d4a 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -24,6 +24,7 @@
import android.annotation.SystemService;
import android.content.Context;
import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -735,7 +736,20 @@
}
}
+ /**
+ * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
+ * intended for IME developers who should be accessing APIs through the service. APIs in this
+ * class are intended for app developers interacting with the IME.
+ */
+ @Deprecated
public void showStatusIcon(IBinder imeToken, String packageName, int iconId) {
+ showStatusIconInternal(imeToken, packageName, iconId);
+ }
+
+ /**
+ * @hide
+ */
+ public void showStatusIconInternal(IBinder imeToken, String packageName, int iconId) {
try {
mService.updateStatusIcon(imeToken, packageName, iconId);
} catch (RemoteException e) {
@@ -743,7 +757,20 @@
}
}
+ /**
+ * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
+ * intended for IME developers who should be accessing APIs through the service. APIs in
+ * this class are intended for app developers interacting with the IME.
+ */
+ @Deprecated
public void hideStatusIcon(IBinder imeToken) {
+ hideStatusIconInternal(imeToken);
+ }
+
+ /**
+ * @hide
+ */
+ public void hideStatusIconInternal(IBinder imeToken) {
try {
mService.updateStatusIcon(imeToken, null, 0);
} catch (RemoteException e) {
@@ -1121,7 +1148,6 @@
}
}
-
/**
* This method toggles the input method window display.
* If the input window is already displayed, it gets hidden.
@@ -1800,8 +1826,19 @@
* when it was started, which allows it to perform this operation on
* itself.
* @param id The unique identifier for the new input method to be switched to.
+ * @deprecated Use {@link InputMethodService#setInputMethod(String)} instead. This method
+ * was intended for IME developers who should be accessing APIs through the service. APIs in
+ * this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public void setInputMethod(IBinder token, String id) {
+ setInputMethodInternal(token, id);
+ }
+
+ /**
+ * @hide
+ */
+ public void setInputMethodInternal(IBinder token, String id) {
try {
mService.setInputMethod(token, id);
} catch (RemoteException e) {
@@ -1817,8 +1854,21 @@
* itself.
* @param id The unique identifier for the new input method to be switched to.
* @param subtype The new subtype of the new input method to be switched to.
+ * @deprecated Use
+ * {@link InputMethodService#setInputMethodAndSubtype(String, InputMethodSubtype)}
+ * instead. This method was intended for IME developers who should be accessing APIs through
+ * the service. APIs in this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
+ setInputMethodAndSubtypeInternal(token, id, subtype);
+ }
+
+ /**
+ * @hide
+ */
+ public void setInputMethodAndSubtypeInternal(
+ IBinder token, String id, InputMethodSubtype subtype) {
try {
mService.setInputMethodAndSubtype(token, id, subtype);
} catch (RemoteException e) {
@@ -1837,8 +1887,19 @@
* @param flags Provides additional operating flags. Currently may be
* 0 or have the {@link #HIDE_IMPLICIT_ONLY},
* {@link #HIDE_NOT_ALWAYS} bit set.
+ * @deprecated Use {@link InputMethodService#hideSoftInputFromInputMethod(int)}
+ * instead. This method was intended for IME developers who should be accessing APIs through
+ * the service. APIs in this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public void hideSoftInputFromInputMethod(IBinder token, int flags) {
+ hideSoftInputFromInputMethodInternal(token, flags);
+ }
+
+ /**
+ * @hide
+ */
+ public void hideSoftInputFromInputMethodInternal(IBinder token, int flags) {
try {
mService.hideMySoftInput(token, flags);
} catch (RemoteException e) {
@@ -1858,8 +1919,19 @@
* @param flags Provides additional operating flags. Currently may be
* 0 or have the {@link #SHOW_IMPLICIT} or
* {@link #SHOW_FORCED} bit set.
+ * @deprecated Use {@link InputMethodService#showSoftInputFromInputMethod(int)}
+ * instead. This method was intended for IME developers who should be accessing APIs through
+ * the service. APIs in this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public void showSoftInputFromInputMethod(IBinder token, int flags) {
+ showSoftInputFromInputMethodInternal(token, flags);
+ }
+
+ /**
+ * @hide
+ */
+ public void showSoftInputFromInputMethodInternal(IBinder token, int flags) {
try {
mService.showMySoftInput(token, flags);
} catch (RemoteException e) {
@@ -2239,8 +2311,19 @@
* which allows it to perform this operation on itself.
* @return true if the current input method and subtype was successfully switched to the last
* used input method and subtype.
+ * @deprecated Use {@link InputMethodService#switchToLastInputMethod()} instead. This method
+ * was intended for IME developers who should be accessing APIs through the service. APIs in
+ * this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public boolean switchToLastInputMethod(IBinder imeToken) {
+ return switchToLastInputMethodInternal(imeToken);
+ }
+
+ /**
+ * @hide
+ */
+ public boolean switchToLastInputMethodInternal(IBinder imeToken) {
synchronized (mH) {
try {
return mService.switchToLastInputMethod(imeToken);
@@ -2259,8 +2342,19 @@
* belongs to the current IME
* @return true if the current input method and subtype was successfully switched to the next
* input method and subtype.
+ * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
+ * method was intended for IME developers who should be accessing APIs through the service.
+ * APIs in this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
+ return switchToNextInputMethodInternal(imeToken, onlyCurrentIme);
+ }
+
+ /**
+ * @hide
+ */
+ public boolean switchToNextInputMethodInternal(IBinder imeToken, boolean onlyCurrentIme) {
synchronized (mH) {
try {
return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
@@ -2280,8 +2374,19 @@
* between IMEs and subtypes.
* @param imeToken Supplies the identifying token given to an input method when it was started,
* which allows it to perform this operation on itself.
+ * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
+ * instead. This method was intended for IME developers who should be accessing APIs through
+ * the service. APIs in this class are intended for app developers interacting with the IME.
*/
+ @Deprecated
public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
+ return shouldOfferSwitchingToNextInputMethodInternal(imeToken);
+ }
+
+ /**
+ * @hide
+ */
+ public boolean shouldOfferSwitchingToNextInputMethodInternal(IBinder imeToken) {
synchronized (mH) {
try {
return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index f4cbc54..fdc9f92 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -48,8 +48,13 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @StringDef({
- TYPE_UNKNOWN, TYPE_OTHER, TYPE_EMAIL, TYPE_PHONE, TYPE_ADDRESS, TYPE_URL
+ @StringDef(prefix = { "TYPE_" }, value = {
+ TYPE_UNKNOWN,
+ TYPE_OTHER,
+ TYPE_EMAIL,
+ TYPE_PHONE,
+ TYPE_ADDRESS,
+ TYPE_URL,
})
@interface EntityType {}
diff --git a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
index 931eb99..45555bf 100644
--- a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
+++ b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
@@ -26,7 +26,15 @@
*/
public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbackProvider {
- private final Choreographer mChoreographer = Choreographer.getSfInstance();
+ private final Choreographer mChoreographer;
+
+ public SfVsyncFrameCallbackProvider() {
+ mChoreographer = Choreographer.getSfInstance();
+ }
+
+ public SfVsyncFrameCallbackProvider(Choreographer choreographer) {
+ mChoreographer = choreographer;
+ }
@Override
public void postFrameCallback(Choreographer.FrameCallback callback) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 4354486..8848e393 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -33,6 +33,7 @@
import android.provider.Downloads;
import android.text.TextUtils;
import android.util.AtomicFile;
+import android.util.EventLog;
import android.util.Slog;
import android.util.Xml;
@@ -40,6 +41,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
+import com.android.server.DropboxLogTags;
import java.io.File;
import java.io.FileInputStream;
@@ -297,6 +299,7 @@
Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") +
footers);
+ EventLog.writeEvent(DropboxLogTags.DROPBOX_FILE_COPY, filename, maxSize, tag);
}
private static void addAuditErrorsToDropBox(DropBoxManager db,
diff --git a/core/java/com/android/server/DropboxLogTags.logtags b/core/java/com/android/server/DropboxLogTags.logtags
new file mode 100644
index 0000000..c461cfe
--- /dev/null
+++ b/core/java/com/android/server/DropboxLogTags.logtags
@@ -0,0 +1,12 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+# The java package name happens to be the same as frameworks/base/services/core
+# /java/com/android/server/EventLogTags.logtags. To avoid conflict, this file's name cannot
+# be EventLogTags.logtags because it generates a class with the same name.
+
+option java_package com.android.server;
+
+# -----------------------------
+# BootReceiver.java
+# -----------------------------
+81002 dropbox_file_copy (FileName|3),(Size|1),(Tag|3)
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 8ed958d..4015a7e 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -45,12 +45,21 @@
package android.os;
+// This field contains internal metadata associated with an incident report,
+// such as the section ids and privacy policy specs from caller as well as how long
+// and how many bytes a section takes, etc.
+message IncidentMetadata {
+
+}
+
// privacy field options must not be set at this level because all
// the sections are able to be controlled and configured by section ids.
// Instead privacy field options need to be configured in each section proto message.
message IncidentProto {
- // Incident header
+ // Incident header from callers
repeated IncidentHeaderProto header = 1;
+ // Internal metadata of incidentd
+ optional IncidentMetadata metadata = 2;
// Device information
optional SystemPropertiesProto system_properties = 1000 [
diff --git a/core/proto/android/os/incidentheader.proto b/core/proto/android/os/incidentheader.proto
index ce924da..f0c736a 100644
--- a/core/proto/android/os/incidentheader.proto
+++ b/core/proto/android/os/incidentheader.proto
@@ -16,18 +16,34 @@
syntax = "proto2";
option java_multiple_files = true;
-option java_outer_classname = "IncidentHeaderProtoMetadata";
package android.os;
+// IncidentHeaderProto contains extra information the caller of incidentd want to
+// attach in an incident report, the data should just be informative.
message IncidentHeaderProto {
- enum Cause {
- CAUSE_UNKNOWN = 0;
- CAUSE_USER = 1;
- CAUSE_ANR = 2;
- CAUSE_CRASH = 3;
+
+ // From statsd config, the name of the anomaly, usually human readable.
+ optional string incident_name = 1;
+
+ // Format a human readable reason why an incident report is requested.
+ // It's optional and may directly come from a user clicking the bug-report button.
+ optional string reason = 2;
+
+ // From statsd, the metric which causes the anomaly triggered.
+ optional string metric_name = 3;
+
+ // From statsd, the metric value exceeds the threshold. This is useful for
+ // ValueMetric and GaugeMetric.
+ oneof metric_value {
+ int64 int64_value = 4;
+ double double_value = 5;
}
- optional Cause cause = 1;
+ // Defines which stats config used to fire the request.
+ message StatsdConfigKey {
+ optional int32 uid = 1;
+ optional string name = 2;
+ }
+ optional StatsdConfigKey config_key = 6;
}
-
diff --git a/core/tests/ConnectivityManagerTest/Android.mk b/core/tests/ConnectivityManagerTest/Android.mk
index 39cf4a4..5ed93f3 100644
--- a/core/tests/ConnectivityManagerTest/Android.mk
+++ b/core/tests/ConnectivityManagerTest/Android.mk
@@ -18,8 +18,8 @@
# We only want this apk build for tests.
LOCAL_MODULE_TAGS := tests
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/core/tests/bandwidthtests/Android.mk b/core/tests/bandwidthtests/Android.mk
index 2af92df..ff9a0fe 100644
--- a/core/tests/bandwidthtests/Android.mk
+++ b/core/tests/bandwidthtests/Android.mk
@@ -22,8 +22,12 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := \
+ android.test.runner \
+ org.apache.http.legacy \
+ android.test.base \
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := BandwidthTests
include $(BUILD_PACKAGE)
diff --git a/core/tests/bluetoothtests/Android.mk b/core/tests/bluetoothtests/Android.mk
index f53419a..744e5b0 100644
--- a/core/tests/bluetoothtests/Android.mk
+++ b/core/tests/bluetoothtests/Android.mk
@@ -8,8 +8,8 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := BluetoothTests
LOCAL_CERTIFICATE := platform
diff --git a/core/tests/coretests/src/android/security/recoverablekeystore/RecoverableKeyGeneratorTest.java b/core/tests/coretests/src/android/security/recoverablekeystore/RecoverableKeyGeneratorTest.java
new file mode 100644
index 0000000..d85d3b8
--- /dev/null
+++ b/core/tests/coretests/src/android/security/recoverablekeystore/RecoverableKeyGeneratorTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.recoverablekeystore;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.security.KeyStore;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RecoverableKeyGeneratorTest {
+ private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+ private static final String KEY_ALGORITHM = "AES";
+ private static final String TEST_ALIAS = "karlin";
+ private static final String WRAPPING_KEY_ALIAS = "RecoverableKeyGeneratorTestWrappingKey";
+
+ @Mock RecoverableKeyStorage mRecoverableKeyStorage;
+
+ @Captor ArgumentCaptor<KeyProtection> mKeyProtectionArgumentCaptor;
+
+ private AndroidKeyStoreSecretKey mPlatformKey;
+ private SecretKey mKeyHandle;
+ private RecoverableKeyGenerator mRecoverableKeyGenerator;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mPlatformKey = generateAndroidKeyStoreKey();
+ mKeyHandle = generateKey();
+ mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(
+ mPlatformKey, mRecoverableKeyStorage);
+
+ when(mRecoverableKeyStorage.loadFromAndroidKeyStore(any())).thenReturn(mKeyHandle);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+ keyStore.load(/*param=*/ null);
+ keyStore.deleteEntry(WRAPPING_KEY_ALIAS);
+ }
+
+ @Test
+ public void generateAndStoreKey_setsKeyInKeyStore() throws Exception {
+ mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+ verify(mRecoverableKeyStorage, times(1))
+ .importIntoAndroidKeyStore(eq(TEST_ALIAS), any(), any());
+ }
+
+ @Test
+ public void generateAndStoreKey_storesKeyEnabledForEncryptDecrypt() throws Exception {
+ mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+ KeyProtection keyProtection = getKeyProtectionUsed();
+ assertEquals(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT,
+ keyProtection.getPurposes());
+ }
+
+ @Test
+ public void generateAndStoreKey_storesKeyEnabledForGCM() throws Exception {
+ mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+ KeyProtection keyProtection = getKeyProtectionUsed();
+ assertArrayEquals(new String[] { KeyProperties.BLOCK_MODE_GCM },
+ keyProtection.getBlockModes());
+ }
+
+ @Test
+ public void generateAndStoreKey_storesKeyEnabledForNoPadding() throws Exception {
+ mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+ KeyProtection keyProtection = getKeyProtectionUsed();
+ assertArrayEquals(new String[] { KeyProperties.ENCRYPTION_PADDING_NONE },
+ keyProtection.getEncryptionPaddings());
+ }
+
+ @Test
+ public void generateAndStoreKey_storesWrappedKey() throws Exception {
+ mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+ verify(mRecoverableKeyStorage, times(1)).persistToDisk(eq(TEST_ALIAS), any());
+ }
+
+ @Test
+ public void generateAndStoreKey_returnsKeyHandle() throws Exception {
+ SecretKey secretKey = mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+ assertEquals(mKeyHandle, secretKey);
+ }
+
+ private KeyProtection getKeyProtectionUsed() throws Exception {
+ verify(mRecoverableKeyStorage, times(1)).importIntoAndroidKeyStore(
+ any(), any(), mKeyProtectionArgumentCaptor.capture());
+ return mKeyProtectionArgumentCaptor.getValue();
+ }
+
+ private SecretKey generateKey() throws Exception {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
+ keyGenerator.init(/*keySize=*/ 256);
+ return keyGenerator.generateKey();
+ }
+
+ private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ KEY_ALGORITHM,
+ ANDROID_KEY_STORE_PROVIDER);
+ keyGenerator.init(new KeyGenParameterSpec.Builder(
+ WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ return (AndroidKeyStoreSecretKey) keyGenerator.generateKey();
+ }
+}
diff --git a/core/tests/coretests/src/android/security/recoverablekeystore/WrappedKeyTest.java b/core/tests/coretests/src/android/security/recoverablekeystore/WrappedKeyTest.java
new file mode 100644
index 0000000..233c821
--- /dev/null
+++ b/core/tests/coretests/src/android/security/recoverablekeystore/WrappedKeyTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.recoverablekeystore;
+
+import static org.junit.Assert.assertEquals;
+
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.KeyStore;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WrappedKeyTest {
+ private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+ private static final String KEY_ALGORITHM = "AES";
+ private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+ private static final String WRAPPING_KEY_ALIAS = "WrappedKeyTestWrappingKeyAlias";
+ private static final int GCM_TAG_LENGTH_BYTES = 16;
+ private static final int BITS_PER_BYTE = 8;
+ private static final int GCM_TAG_LENGTH_BITS = GCM_TAG_LENGTH_BYTES * BITS_PER_BYTE;
+
+ @After
+ public void tearDown() throws Exception {
+ KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+ keyStore.load(/*param=*/ null);
+ keyStore.deleteEntry(WRAPPING_KEY_ALIAS);
+ }
+
+ @Test
+ public void fromSecretKey_createsWrappedKeyThatCanBeUnwrapped() throws Exception {
+ SecretKey wrappingKey = generateAndroidKeyStoreKey();
+ SecretKey rawKey = generateKey();
+
+ WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey);
+
+ Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+ cipher.init(
+ Cipher.UNWRAP_MODE,
+ wrappingKey,
+ new GCMParameterSpec(GCM_TAG_LENGTH_BITS, wrappedKey.getNonce()));
+ SecretKey unwrappedKey = (SecretKey) cipher.unwrap(
+ wrappedKey.getKeyMaterial(), KEY_ALGORITHM, Cipher.SECRET_KEY);
+ assertEquals(rawKey, unwrappedKey);
+ }
+
+ private SecretKey generateKey() throws Exception {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
+ keyGenerator.init(/*keySize=*/ 256);
+ return keyGenerator.generateKey();
+ }
+
+ private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ KEY_ALGORITHM,
+ ANDROID_KEY_STORE_PROVIDER);
+ keyGenerator.init(new KeyGenParameterSpec.Builder(
+ WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ return (AndroidKeyStoreSecretKey) keyGenerator.generateKey();
+ }
+}
diff --git a/core/tests/coretests/src/android/util/ScrollViewScenario.java b/core/tests/coretests/src/android/util/ScrollViewScenario.java
index b5140e3..e9eb978 100644
--- a/core/tests/coretests/src/android/util/ScrollViewScenario.java
+++ b/core/tests/coretests/src/android/util/ScrollViewScenario.java
@@ -269,6 +269,6 @@
mScrollView.setSmoothScrollingEnabled(false);
setContentView(mScrollView);
- mScrollView.restoreDefaultFocus();
+ mScrollView.post(() -> mScrollView.restoreDefaultFocus());
}
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index 8a5fc2d..c1b2309 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -24,6 +24,7 @@
import android.os.RemoteException;
import android.support.test.runner.AndroidJUnit4;
+import libcore.util.EmptyArray;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -73,7 +74,7 @@
List<AccessibilityNodeInfo> mInfosToReturn;
@Override
- public boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+ public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
Bundle arguments) {
@@ -82,7 +83,7 @@
} catch (RemoteException e) {
throw new RuntimeException(e);
}
- return true;
+ return EmptyArray.STRING;
}
}
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index d3bbee7..44b1f08 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -31,35 +31,35 @@
public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceConnection.Stub {
public void setServiceInfo(AccessibilityServiceInfo info) {}
- public boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+ public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
Bundle arguments) {
- return false;
+ return null;
}
- public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
+ public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
long accessibilityNodeId, String text, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId) {
- return false;
+ return null;
}
- public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+ public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId) {
- return false;
+ return null;
}
- public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
+ public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId) {
- return false;
+ return null;
}
- public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
+ public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId) {
- return false;
+ return null;
}
public boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
index 47ee2cf..1d9f624 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
@@ -20,8 +20,8 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := android-common mockwebserver junit legacy-android-test
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-common mockwebserver junit
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_PACKAGE_NAME := DownloadManagerTestApp
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk
index b35cbae..193e601 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_SDK_VERSION := current
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk
index 06812b5..9f44767 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_SDK_VERSION := current
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk
index 48bceaf..b4d354c 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_SDK_VERSION := current
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk
index 569d102..969e588 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_SDK_VERSION := current
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
index 0551eb6..30c2dca 100644
--- a/core/tests/notificationtests/Android.mk
+++ b/core/tests/notificationtests/Android.mk
@@ -8,12 +8,11 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_PACKAGE_NAME := NotificationStressTests
LOCAL_STATIC_JAVA_LIBRARIES := \
junit \
- legacy-android-test \
ub-uiautomator
include $(BUILD_PACKAGE)
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index d6b1cf1..a250d1f 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -39,13 +39,12 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true,
- value = {
- PURPOSE_ENCRYPT,
- PURPOSE_DECRYPT,
- PURPOSE_SIGN,
- PURPOSE_VERIFY,
- })
+ @IntDef(flag = true, prefix = { "PURPOSE_" }, value = {
+ PURPOSE_ENCRYPT,
+ PURPOSE_DECRYPT,
+ PURPOSE_SIGN,
+ PURPOSE_VERIFY,
+ })
public @interface PurposeEnum {}
/**
@@ -126,7 +125,7 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @StringDef({
+ @StringDef(prefix = { "KEY_" }, value = {
KEY_ALGORITHM_RSA,
KEY_ALGORITHM_EC,
KEY_ALGORITHM_AES,
@@ -267,7 +266,7 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @StringDef({
+ @StringDef(prefix = { "BLOCK_MODE_" }, value = {
BLOCK_MODE_ECB,
BLOCK_MODE_CBC,
BLOCK_MODE_CTR,
@@ -354,7 +353,7 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @StringDef({
+ @StringDef(prefix = { "ENCRYPTION_PADDING_" }, value = {
ENCRYPTION_PADDING_NONE,
ENCRYPTION_PADDING_PKCS7,
ENCRYPTION_PADDING_RSA_PKCS1,
@@ -437,7 +436,7 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @StringDef({
+ @StringDef(prefix = { "SIGNATURE_PADDING_" }, value = {
SIGNATURE_PADDING_RSA_PKCS1,
SIGNATURE_PADDING_RSA_PSS,
})
@@ -497,7 +496,7 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @StringDef({
+ @StringDef(prefix = { "DIGEST_" }, value = {
DIGEST_NONE,
DIGEST_MD5,
DIGEST_SHA1,
@@ -647,11 +646,12 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef({
- ORIGIN_GENERATED,
- ORIGIN_IMPORTED,
- ORIGIN_UNKNOWN,
- })
+ @IntDef(prefix = { "ORIGIN_" }, value = {
+ ORIGIN_GENERATED,
+ ORIGIN_IMPORTED,
+ ORIGIN_UNKNOWN,
+ })
+
public @interface OriginEnum {}
/** Key was generated inside AndroidKeyStore. */
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index b15e0a2..7cb8e37 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -81,12 +81,16 @@
}
out.writeByteArray(mSpec.getCertificateSubject().getEncoded());
out.writeByteArray(mSpec.getCertificateSerialNumber().toByteArray());
- writeOptionalDate(out, mSpec.getCertificateNotBefore());
- writeOptionalDate(out, mSpec.getCertificateNotAfter());
+ out.writeLong(mSpec.getCertificateNotBefore().getTime());
+ out.writeLong(mSpec.getCertificateNotAfter().getTime());
writeOptionalDate(out, mSpec.getKeyValidityStart());
writeOptionalDate(out, mSpec.getKeyValidityForOriginationEnd());
writeOptionalDate(out, mSpec.getKeyValidityForConsumptionEnd());
- out.writeStringArray(mSpec.getDigests());
+ if (mSpec.isDigestsSpecified()) {
+ out.writeStringArray(mSpec.getDigests());
+ } else {
+ out.writeStringArray(null);
+ }
out.writeStringArray(mSpec.getEncryptionPaddings());
out.writeStringArray(mSpec.getSignaturePaddings());
out.writeStringArray(mSpec.getBlockModes());
@@ -111,9 +115,15 @@
private ParcelableKeyGenParameterSpec(Parcel in) {
String keystoreAlias = in.readString();
int purposes = in.readInt();
- KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keystoreAlias, purposes);
+ KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(
+ keystoreAlias, purposes);
builder.setUid(in.readInt());
- builder.setKeySize(in.readInt());
+ // KeySize is -1 by default, if the KeyGenParameterSpec previously parcelled had the default
+ // value, do not set it as this will cause setKeySize to throw.
+ int keySize = in.readInt();
+ if (keySize >= 0) {
+ builder.setKeySize(keySize);
+ }
int keySpecType = in.readInt();
AlgorithmParameterSpec algorithmSpec = null;
@@ -128,17 +138,22 @@
algorithmSpec = new ECGenParameterSpec(stdName);
} else {
throw new IllegalArgumentException(
- String.format("Unknown algorithm parameter spec: %d", algorithmSpec));
+ String.format("Unknown algorithm parameter spec: %d", keySpecType));
}
- builder.setAlgorithmParameterSpec(algorithmSpec);
+ if (algorithmSpec != null) {
+ builder.setAlgorithmParameterSpec(algorithmSpec);
+ }
builder.setCertificateSubject(new X500Principal(in.createByteArray()));
builder.setCertificateSerialNumber(new BigInteger(in.createByteArray()));
- builder.setCertificateNotBefore(readDateOrNull(in));
- builder.setCertificateNotAfter(readDateOrNull(in));
+ builder.setCertificateNotBefore(new Date(in.readLong()));
+ builder.setCertificateNotAfter(new Date(in.readLong()));
builder.setKeyValidityStart(readDateOrNull(in));
builder.setKeyValidityForOriginationEnd(readDateOrNull(in));
builder.setKeyValidityForConsumptionEnd(readDateOrNull(in));
- builder.setDigests(in.createStringArray());
+ String[] digests = in.createStringArray();
+ if (digests != null) {
+ builder.setDigests(digests);
+ }
builder.setEncryptionPaddings(in.createStringArray());
builder.setSignaturePaddings(in.createStringArray());
builder.setBlockModes(in.createStringArray());
diff --git a/keystore/tests/Android.mk b/keystore/tests/Android.mk
index 51adde4..1167f76 100644
--- a/keystore/tests/Android.mk
+++ b/keystore/tests/Android.mk
@@ -21,8 +21,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
- android-support-test \
- legacy-android-test
+ android-support-test
LOCAL_PACKAGE_NAME := KeystoreTests
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 96e4fcf..7cacaf6 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -122,7 +122,7 @@
instrumentation: true,
profile_file: "hwui/hwui.profdata",
benchmarks: ["hwui"],
- enable_profile_use: false,
+ enable_profile_use: true,
},
}
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 77d7bef..4ddacc8 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -42,8 +42,15 @@
mBounds.set(left, top, right, bottom);
mRadius = radius;
+
+ // Reuse memory if previous outline was the same shape (rect or round rect).
+ if ( mPath.countVerbs() > 10) {
+ mPath.reset();
+ } else {
+ mPath.rewind();
+ }
+
// update mPath to reflect new outline
- mPath.reset();
if (MathUtils::isPositive(radius)) {
mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radius, radius);
} else {
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 12e5744..e2f9b47 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -977,7 +977,7 @@
public static final String PROPERTY_ALGORITHMS = "algorithms";
/** @hide */
- @StringDef({
+ @StringDef(prefix = { "PROPERTY_" }, value = {
PROPERTY_VENDOR,
PROPERTY_VERSION,
PROPERTY_DESCRIPTION,
@@ -1010,7 +1010,7 @@
public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
/** @hide */
- @StringDef({
+ @StringDef(prefix = { "PROPERTY_" }, value = {
PROPERTY_DEVICE_UNIQUE_ID,
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 31eb948..94d4d55 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -45,34 +45,61 @@
/**
* @hide
*/
- @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR,
- METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION,
- METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI,
- METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE,
- METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI,
- METADATA_KEY_MEDIA_ID, METADATA_KEY_MEDIA_URI})
+ @StringDef(prefix = { "METADATA_KEY_" }, value = {
+ METADATA_KEY_TITLE,
+ METADATA_KEY_ARTIST,
+ METADATA_KEY_ALBUM,
+ METADATA_KEY_AUTHOR,
+ METADATA_KEY_WRITER,
+ METADATA_KEY_COMPOSER,
+ METADATA_KEY_COMPILATION,
+ METADATA_KEY_DATE,
+ METADATA_KEY_GENRE,
+ METADATA_KEY_ALBUM_ARTIST,
+ METADATA_KEY_ART_URI,
+ METADATA_KEY_ALBUM_ART_URI,
+ METADATA_KEY_DISPLAY_TITLE,
+ METADATA_KEY_DISPLAY_SUBTITLE,
+ METADATA_KEY_DISPLAY_DESCRIPTION,
+ METADATA_KEY_DISPLAY_ICON_URI,
+ METADATA_KEY_MEDIA_ID,
+ METADATA_KEY_MEDIA_URI,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface TextKey {}
/**
* @hide
*/
- @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER,
- METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER, METADATA_KEY_BT_FOLDER_TYPE})
+ @StringDef(prefix = { "METADATA_KEY_" }, value = {
+ METADATA_KEY_DURATION,
+ METADATA_KEY_YEAR,
+ METADATA_KEY_TRACK_NUMBER,
+ METADATA_KEY_NUM_TRACKS,
+ METADATA_KEY_DISC_NUMBER,
+ METADATA_KEY_BT_FOLDER_TYPE,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface LongKey {}
/**
* @hide
*/
- @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON})
+ @StringDef(prefix = { "METADATA_KEY_" }, value = {
+ METADATA_KEY_ART,
+ METADATA_KEY_ALBUM_ART,
+ METADATA_KEY_DISPLAY_ICON,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface BitmapKey {}
/**
* @hide
*/
- @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING})
+ @StringDef(prefix = { "METADATA_KEY_" }, value = {
+ METADATA_KEY_USER_RATING,
+ METADATA_KEY_RATING,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface RatingKey {}
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 8283c8b..17d16b8 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -17,6 +17,7 @@
import android.annotation.DrawableRes;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.Nullable;
import android.media.RemoteControlClient;
import android.os.Bundle;
@@ -41,7 +42,7 @@
/**
* @hide
*/
- @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+ @LongDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 0f46096..3bbc2c4 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1650,7 +1650,7 @@
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
/** @hide */
- @StringDef({
+ @StringDef(prefix = { "TYPE_" }, value = {
TYPE_OTHER,
TYPE_NTSC,
TYPE_PAL,
@@ -1863,7 +1863,7 @@
public static final String TYPE_PREVIEW = "TYPE_PREVIEW";
/** @hide */
- @StringDef({
+ @StringDef(prefix = { "SERVICE_TYPE_" }, value = {
SERVICE_TYPE_OTHER,
SERVICE_TYPE_AUDIO_VIDEO,
SERVICE_TYPE_AUDIO,
@@ -1881,7 +1881,7 @@
public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
/** @hide */
- @StringDef({
+ @StringDef(prefix = { "VIDEO_FORMAT_" }, value = {
VIDEO_FORMAT_240P,
VIDEO_FORMAT_360P,
VIDEO_FORMAT_480I,
@@ -1930,7 +1930,7 @@
public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P";
/** @hide */
- @StringDef({
+ @StringDef(prefix = { "VIDEO_RESOLUTION_" }, value = {
VIDEO_RESOLUTION_SD,
VIDEO_RESOLUTION_ED,
VIDEO_RESOLUTION_HD,
diff --git a/media/mca/tests/Android.mk b/media/mca/tests/Android.mk
index eb451f7..394f542 100644
--- a/media/mca/tests/Android.mk
+++ b/media/mca/tests/Android.mk
@@ -4,8 +4,8 @@
# We only want this apk build for tests.
LOCAL_MODULE_TAGS := tests
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index 0d9f42b..145cde6 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -5,13 +5,12 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_STATIC_JAVA_LIBRARIES := \
mockito-target-minus-junit4 \
android-support-test \
- android-ex-camera2 \
- legacy-android-test
+ android-ex-camera2
LOCAL_PACKAGE_NAME := mediaframeworktest
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
index d8fe5a6..be2bb53 100644
--- a/nfc-extras/tests/Android.mk
+++ b/nfc-extras/tests/Android.mk
@@ -22,7 +22,7 @@
android.test.runner \
com.android.nfc_extras
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
index 63bd0b1..6e120a6 100644
--- a/packages/CarrierDefaultApp/tests/unit/Android.mk
+++ b/packages/CarrierDefaultApp/tests/unit/Android.mk
@@ -19,9 +19,9 @@
LOCAL_MODULE_TAGS := tests
LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target-minus-junit4 legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target-minus-junit4
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/ExtServices/tests/Android.mk b/packages/ExtServices/tests/Android.mk
index 92afbeb..1eb5847 100644
--- a/packages/ExtServices/tests/Android.mk
+++ b/packages/ExtServices/tests/Android.mk
@@ -5,14 +5,13 @@
LOCAL_MODULE_TAGS := tests
LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
mockito-target-minus-junit4 \
espresso-core \
truth-prebuilt \
- legacy-android-test \
testables
# Include all test java files.
diff --git a/packages/InputDevices/res/raw/keyboard_layout_azerbaijani.kcm b/packages/InputDevices/res/raw/keyboard_layout_azerbaijani.kcm
new file mode 100644
index 0000000..69490cc
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_azerbaijani.kcm
@@ -0,0 +1,312 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Azerbaijan (AZ) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '\u2166'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: ';'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: ':'
+ shift+ralt: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '?'
+ ralt: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: '\u00dc'
+ base: '\u00fc'
+ shift, capslock: '\u00dc'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: '\u0130'
+ base: 'i'
+ shift, capslock: '\u0130'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00d6'
+ base: '\u00f6'
+ shift: '\u00d6'
+}
+
+key RIGHT_BRACKET {
+ label: '\u011e'
+ base: '\u011f'
+ shift: '\u011e'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: 'I'
+ base: '\u0131'
+ shift: 'I'
+}
+
+key APOSTROPHE {
+ label: '\u018f'
+ base: '\u0259'
+ shift: '\u018f'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: '\u00c7'
+ base: '\u00e7'
+ shift: '\u00c7'
+}
+
+key PERIOD {
+ label: '\u015e'
+ base: '\u015f'
+ shift: '\u015e'
+}
+
+key SLASH {
+ label: '.'
+ base: '.'
+ shift: ','
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 1e26226..61d3234 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -122,4 +122,7 @@
<!-- Persian keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_persian">Persian</string>
+
+ <!-- Azerbaijani keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_azerbaijani">Azerbaijani</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index c55711a..c6bfc1f 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -155,4 +155,8 @@
<keyboard-layout android:name="keyboard_layout_persian"
android:label="@string/keyboard_layout_persian"
android:keyboardLayout="@raw/keyboard_layout_persian" />
+
+ <keyboard-layout android:name="keyboard_layout_azerbaijani"
+ android:label="@string/keyboard_layout_azerbaijani"
+ android:keyboardLayout="@raw/keyboard_layout_azerbaijani" />
</keyboard-layouts>
diff --git a/packages/MtpDocumentsProvider/tests/Android.mk b/packages/MtpDocumentsProvider/tests/Android.mk
index 148cd0d..ba346f42 100644
--- a/packages/MtpDocumentsProvider/tests/Android.mk
+++ b/packages/MtpDocumentsProvider/tests/Android.mk
@@ -3,8 +3,8 @@
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := MtpDocumentsProviderTests
LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
LOCAL_CERTIFICATE := media
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 3c8c8ac..cfb3519d 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
LOCAL_JACK_FLAGS := --multi-dex native
@@ -33,7 +33,6 @@
android-support-test \
espresso-core \
mockito-target-minus-junit4 \
- legacy-android-test \
truth-prebuilt
# Code coverage puts us over the dex limit, so enable multi-dex for coverage-enabled builds
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
index 069e83a..0f2c5ab 100644
--- a/packages/SettingsProvider/Android.mk
+++ b/packages/SettingsProvider/Android.mk
@@ -7,7 +7,7 @@
src/com/android/providers/settings/EventLogTags.logtags
LOCAL_JAVA_LIBRARIES := telephony-common ims-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := SettingsProvider
LOCAL_CERTIFICATE := platform
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 9374d52..287a888 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -11,6 +11,8 @@
android:icon="@mipmap/ic_launcher_settings"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
+ <uses-library android:name="android.test.runner" />
+
<provider android:name="SettingsProvider"
android:authorities="settings"
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index 48b757c..7f24a38 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -6,14 +6,13 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
mockito-target-minus-junit4 \
ub-uiautomator \
junit \
- legacy-android-test \
LOCAL_PACKAGE_NAME := ShellTests
LOCAL_COMPATIBILITY_SUITE := device-tests
diff --git a/packages/SystemUI/shared/tests/Android.mk b/packages/SystemUI/shared/tests/Android.mk
index ce3b442..239a4e3 100644
--- a/packages/SystemUI/shared/tests/Android.mk
+++ b/packages/SystemUI/shared/tests/Android.mk
@@ -38,7 +38,6 @@
mockito-target-minus-junit4 \
SystemUI-proto \
SystemUI-tags \
- legacy-android-test \
testables \
truth-prebuilt \
@@ -50,4 +49,4 @@
ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
include $(BUILD_PACKAGE)
-endif
\ No newline at end of file
+endif
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3b54e11..5c8c3f35 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -333,7 +333,7 @@
} else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
mItems.add(new RestartAction());
} else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) {
- if (mDevicePolicyManager.isLogoutButtonEnabled()
+ if (mDevicePolicyManager.isLogoutEnabled()
&& getCurrentUser().id != UserHandle.USER_SYSTEM) {
mItems.add(new LogoutAction());
mHasLogoutButton = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 3a36776..05fcbb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -204,12 +204,15 @@
throw new IllegalArgumentException("Cannot change to UNINITIALIZED.");
}
+ final ScrimState oldState = mState;
+ mState = state;
+
if (mCallback != null) {
mCallback.onCancelled();
}
mCallback = callback;
- state.prepare(mState);
+ state.prepare(oldState);
mScreenBlankingCallbackCalled = false;
mAnimationDelay = 0;
mBlankScreen = state.getBlanksScreen();
@@ -228,8 +231,6 @@
mKeyguardFadeoutAnimation.cancel();
}
- mState = state;
-
// Do not let the device sleep until we're done with all animations
if (!mWakeLockHeld) {
if (mWakeLock != null) {
@@ -310,7 +311,6 @@
mCurrentInFrontAlpha = 0;
}
} else {
- Log.w(TAG, "Invalid state, cannot set panel expansion when: " + mState);
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 80bab72..c61b7e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -661,8 +661,7 @@
@Override
public void onCancelled() {
- // Transition was cancelled because another one took over.
- // Nothing to do in here but wait.
+ onFinished();
}
};
@@ -4140,14 +4139,10 @@
.setStartDelay(0)
.setDuration(FADE_KEYGUARD_DURATION_PULSING)
.setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- hideKeyguard();
- mStatusBarKeyguardViewManager.onKeyguardFadedAway();
- }
- })
- .start();
+ .withEndAction(()-> {
+ hideKeyguard();
+ mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+ }).start();
}
/**
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 195607d..7374f11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -448,7 +448,7 @@
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
childState.hidden = false;
ExpandableViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
- if (!isTopEntry && (!mIsExpanded
+ if (topState != null && !isTopEntry && (!mIsExpanded
|| unmodifiedEndLocation < topState.yTranslation + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
// the top most z-position
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index b695919..9d44895 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -54,11 +54,15 @@
mockito-target-minus-junit4 \
SystemUI-proto \
SystemUI-tags \
- legacy-android-test \
testables \
truth-prebuilt \
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.car
+LOCAL_JAVA_LIBRARIES := \
+ android.test.runner \
+ telephony-common \
+ android.car \
+ android.test.base \
+
LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
diff --git a/packages/VpnDialogs/res/values-bs/strings.xml b/packages/VpnDialogs/res/values-bs/strings.xml
index 1862bb7..56812d5 100644
--- a/packages/VpnDialogs/res/values-bs/strings.xml
+++ b/packages/VpnDialogs/res/values-bs/strings.xml
@@ -24,7 +24,7 @@
<string name="data_transmitted" msgid="7988167672982199061">"Poslano:"</string>
<string name="data_received" msgid="4062776929376067820">"Primljeno:"</string>
<string name="data_value_format" msgid="2192466557826897580">"Broj bajtova: <xliff:g id="NUMBER_0">%1$s</xliff:g>/Broj paketa: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
- <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ne može se povezati na stalno uključen VPN"</string>
+ <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nije se moguće povezati na stalno uključen VPN"</string>
<string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikacija <xliff:g id="VPN_APP_0">%1$s</xliff:g> je postavljena da ostane povezana sve vrijeme, ali se trenutno ne može povezati. Telefon će koristiti javnu mrežu dok se ponovo ne mogne povezati s aplikacijom <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string>
<string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikacija <xliff:g id="VPN_APP">%1$s</xliff:g> je postavljena da ostane povezana sve vrijeme, ali se trenutno ne može povezati. Nećete biti imati vezu dok se VPN ne mogne ponovo povezati."</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
diff --git a/packages/WAPPushManager/tests/Android.mk b/packages/WAPPushManager/tests/Android.mk
index 1dea798..bfc85ab 100644
--- a/packages/WAPPushManager/tests/Android.mk
+++ b/packages/WAPPushManager/tests/Android.mk
@@ -18,8 +18,8 @@
# We only want this apk build for tests.
LOCAL_MODULE_TAGS := tests
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ba6bb23..935b787 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3953,6 +3953,10 @@
// An autofill session was started
// Package: Package of app that is autofilled
+ // NOTE: starting on OS MR1, it also added the following field:
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // NOTE: starting on OS P, it also added the following field:
+ // Tag FIELD_FLAGS - Flags used to start the session
AUTOFILL_SESSION_STARTED = 906;
// An autofill request was processed by a service
@@ -3960,7 +3964,11 @@
// Type TYPE_FAILURE: The request failed
// Package: Package of app that is autofilled
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // Tag FIELD_AUTOFILL_NUM_DATASET: The number of datasets returned (only in success case)
+ // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets returned (only in success case)
+ // NOTE: starting on OS P, it also added:
+ // Type TYPE_CLOSE: Service returned a null response.
+ // Tag FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS: if service requested field classification,
+ // number of entries field ids in the request.
AUTOFILL_REQUEST = 907;
// Tag of a field for a package of an autofill service
@@ -4863,7 +4871,6 @@
// Counter: duration (in ms) that autofill will be disabled
// OS: P
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // Tag FIELD_CLASS_NAME: Name of the Package of service that processed the request
AUTOFILL_SERVICE_DISABLED_APP = 1231;
// An autofill service asked to disable autofill for a given activity.
@@ -5067,6 +5074,26 @@
// OS: P
NOTIFICATION_ZEN_MODE_RULE_SELECTION_DIALOG = 1270;
+ // Tag of a field for the number of ids in an autofill field classification request.
+ FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS = 1271;
+
+ // An autofill service updated its user data
+ // Package: Package of the autofill service that updated the user data
+ // Counter: number of fields added (or 0 if reset)
+ // OS: P
+ AUTOFILL_USERDATA_UPDATED = 1272;
+
+ // Some data entered by the user matched the field classification requested by the service.
+ // Package: Package of app that is autofilled
+ // Counter: number of matches found
+ // OS: P
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_MATCH_SCORE: Average score of the matches, in the range of 0 to 100
+ AUTOFILL_FIELD_CLASSIFICATION_MATCHES = 1273;
+
+ // Tag used to report autofill field classification scores
+ FIELD_AUTOFILL_MATCH_SCORE = 1274;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 75d080d..d817da5 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -187,6 +187,12 @@
// to a Wi-Fi network
NOTE_WIFI_WRONG_PASSWORD = 42;
+ // Inform the user that Wifi Wake will re-enable wifi when possible
+ NOTE_WIFI_WAKE_ONBOARD = 43;
+
+ // Inform the user that Wifi Wake has automatically re-enabled Wifi
+ NOTE_WIFI_WAKE_TURNED_BACK_ON = 44;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/sax/tests/saxtests/Android.mk b/sax/tests/saxtests/Android.mk
index d3fbd05..e0e490c 100644
--- a/sax/tests/saxtests/Android.mk
+++ b/sax/tests/saxtests/Android.mk
@@ -7,8 +7,8 @@
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := FrameworksSaxTests
include $(BUILD_PACKAGE)
diff --git a/services/Android.bp b/services/Android.bp
index 84c45fe..5e75c37 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,46 @@
+// merge all required services into one jar
+// ============================================================
+java_library {
+ name: "services",
+
+ dex_preopt: {
+ app_image: true,
+ profile: "art-profile",
+ },
+
+ srcs: [
+ "java/**/*.java",
+ ],
+
+ // The convention is to name each service module 'services.$(module_name)'
+ static_libs: [
+ "services.core.priorityboosted",
+ "services.accessibility",
+ "services.appwidget",
+ "services.autofill",
+ "services.backup",
+ "services.companion",
+ "services.coverage",
+ "services.devicepolicy",
+ "services.midi",
+ "services.net",
+ "services.print",
+ "services.restrictions",
+ "services.usage",
+ "services.usb",
+ "services.voiceinteraction",
+ "android.hidl.base-V1.0-java",
+ ],
+
+ libs: [
+ "android.hidl.manager-V1.0-java",
+ ],
+
+ // Uncomment to enable output of certain warnings (deprecated, unchecked)
+ //javacflags: ["-Xlint"],
+
+}
+
// native library
// =============================================================
diff --git a/services/Android.mk b/services/Android.mk
deleted file mode 100644
index 81d8181..0000000
--- a/services/Android.mk
+++ /dev/null
@@ -1,67 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# merge all required services into one jar
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services
-LOCAL_DEX_PREOPT_APP_IMAGE := true
-LOCAL_DEX_PREOPT_GENERATE_PROFILE := true
-LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING := $(LOCAL_PATH)/art-profile
-
-LOCAL_SRC_FILES := $(call all-java-files-under,java)
-
-# EventLogTags files.
-LOCAL_SRC_FILES += \
- core/java/com/android/server/EventLogTags.logtags
-
-# Uncomment to enable output of certain warnings (deprecated, unchecked)
-# LOCAL_JAVACFLAGS := -Xlint
-
-# Services that will be built as part of services.jar
-# These should map to directory names relative to this
-# Android.mk.
-services := \
- core \
- accessibility \
- appwidget \
- autofill \
- backup \
- companion \
- coverage\
- devicepolicy \
- midi \
- net \
- print \
- restrictions \
- usage \
- usb \
- voiceinteraction
-
-# The convention is to name each service module 'services.$(module_name)'
-LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services)) \
- android.hidl.base-V1.0-java \
- android.hardware.biometrics.fingerprint-V2.1-java
-
-LOCAL_JAVA_LIBRARIES := \
- android.hidl.manager-V1.0-java
-
-ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
-LOCAL_EMMA_INSTRUMENT := true
-endif
-
-include $(BUILD_JAVA_LIBRARY)
-
-# =============================================================
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-# A full make is happening, so make everything.
-include $(call all-makefiles-under,$(LOCAL_PATH))
-else
-# If we ran an mm[m] command, we still want to build the individual
-# services that we depend on. This differs from the above condition
-# by only including service makefiles and not any tests or other
-# modules.
-include $(patsubst %,$(LOCAL_PATH)/%/Android.mk,$(services))
-endif
-
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
new file mode 100644
index 0000000..f991d7b
--- /dev/null
+++ b/services/accessibility/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.accessibility",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk
deleted file mode 100644
index ce89aa7..0000000
--- a/services/accessibility/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.accessibility
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java
index 7e94d7b..01679dd 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java
@@ -20,9 +20,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
-import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
-import android.accessibilityservice.GestureDescription;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
@@ -49,7 +47,6 @@
import android.view.View;
import android.view.accessibility.AccessibilityCache;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -58,6 +55,7 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
+import com.android.server.accessibility.AccessibilityManagerService.RemoteAccessibilityConnection;
import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy;
import com.android.server.wm.WindowManagerInternal;
@@ -171,13 +169,13 @@
@NonNull MagnificationController getMagnificationController();
/**
- * Resolve a connection for a window id
+ * Resolve a connection wrapper for a window id
*
* @param windowId The id of the window of interest
*
* @return a connection to the window
*/
- IAccessibilityInteractionConnection getConnectionLocked(int windowId);
+ RemoteAccessibilityConnection getConnectionLocked(int windowId);
/**
* Perform the specified accessibility action
@@ -416,28 +414,28 @@
}
@Override
- public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+ public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewIdResName, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
Region partialInteractiveRegion = Region.obtain();
MagnificationSpec spec;
synchronized (mLock) {
mUsesAccessibilityCache = true;
if (!isCalledForCurrentUserLocked()) {
- return false;
+ return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return false;
+ return null;
} else {
connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return false;
+ return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -450,12 +448,14 @@
final int interrogatingPid = Binder.getCallingPid();
callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
interrogatingPid, interrogatingTid);
+ final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
try {
- connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
- partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId,
+ viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags,
interrogatingPid, interrogatingTid, spec);
- return true;
+ return mSecurityPolicy.computeValidReportedPackages(callingUid,
+ connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -463,36 +463,36 @@
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
- if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+ if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
- return false;
+ return null;
}
@Override
- public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
+ public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
long accessibilityNodeId, String text, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
Region partialInteractiveRegion = Region.obtain();
MagnificationSpec spec;
synchronized (mLock) {
mUsesAccessibilityCache = true;
if (!isCalledForCurrentUserLocked()) {
- return false;
+ return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return false;
+ return null;
} else {
connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return false;
+ return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -505,12 +505,14 @@
final int interrogatingPid = Binder.getCallingPid();
callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
interrogatingPid, interrogatingTid);
+ final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
try {
- connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
- partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId,
+ text, partialInteractiveRegion, interactionId, callback, mFetchFlags,
interrogatingPid, interrogatingTid, spec);
- return true;
+ return mSecurityPolicy.computeValidReportedPackages(callingUid,
+ connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -518,36 +520,36 @@
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
- if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+ if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
- return false;
+ return null;
}
@Override
- public boolean findAccessibilityNodeInfoByAccessibilityId(
+ public String[] findAccessibilityNodeInfoByAccessibilityId(
int accessibilityWindowId, long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
long interrogatingTid, Bundle arguments) throws RemoteException {
final int resolvedWindowId;
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
Region partialInteractiveRegion = Region.obtain();
MagnificationSpec spec;
synchronized (mLock) {
mUsesAccessibilityCache = true;
if (!isCalledForCurrentUserLocked()) {
- return false;
+ return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return false;
+ return null;
} else {
connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return false;
+ return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -560,12 +562,14 @@
final int interrogatingPid = Binder.getCallingPid();
callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
interrogatingPid, interrogatingTid);
+ final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
try {
- connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
- partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
- interrogatingPid, interrogatingTid, spec, arguments);
- return true;
+ connection.getRemote().findAccessibilityNodeInfoByAccessibilityId(
+ accessibilityNodeId, partialInteractiveRegion, interactionId, callback,
+ mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, arguments);
+ return mSecurityPolicy.computeValidReportedPackages(callingUid,
+ connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -573,36 +577,36 @@
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
- if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+ if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
- return false;
+ return null;
}
@Override
- public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
+ public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId,
int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
Region partialInteractiveRegion = Region.obtain();
MagnificationSpec spec;
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
- return false;
+ return null;
}
resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
accessibilityWindowId, focusType);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return false;
+ return null;
} else {
connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return false;
+ return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -615,12 +619,14 @@
final int interrogatingPid = Binder.getCallingPid();
callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
interrogatingPid, interrogatingTid);
+ final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
try {
- connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
- interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
- spec);
- return true;
+ connection.getRemote().findFocus(accessibilityNodeId, focusType,
+ partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ interrogatingPid, interrogatingTid, spec);
+ return mSecurityPolicy.computeValidReportedPackages(callingUid,
+ connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findFocus()");
@@ -628,35 +634,35 @@
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
- if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+ if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
- return false;
+ return null;
}
@Override
- public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
+ public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId,
int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
Region partialInteractiveRegion = Region.obtain();
MagnificationSpec spec;
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
- return false;
+ return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return false;
+ return null;
} else {
connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return false;
+ return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -669,12 +675,14 @@
final int interrogatingPid = Binder.getCallingPid();
callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
interrogatingPid, interrogatingTid);
+ final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
try {
- connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
- interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
- spec);
- return true;
+ connection.getRemote().focusSearch(accessibilityNodeId, direction,
+ partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ interrogatingPid, interrogatingTid, spec);
+ return mSecurityPolicy.computeValidReportedPackages(callingUid,
+ connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
@@ -682,11 +690,11 @@
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
- if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+ if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
- return false;
+ return null;
}
@Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0a21b9e..ac0cdd7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -24,12 +24,12 @@
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
-import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
import android.app.AlertDialog;
import android.app.PendingIntent;
+import android.appwidget.AppWidgetManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -72,6 +72,7 @@
import android.provider.SettingsStringUtil.SettingStringHelper;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArraySet;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -97,6 +98,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IntPair;
import com.android.server.LocalServices;
@@ -104,6 +106,7 @@
import com.android.internal.accessibility.AccessibilityShortcutController.ToggleableFrameworkFeatureInfo;
import com.android.server.wm.WindowManagerInternal;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
@@ -186,6 +189,8 @@
private final WindowManagerInternal mWindowManagerService;
+ private AppWidgetManagerInternal mAppWidgetService;
+
private final SecurityPolicy mSecurityPolicy;
private final MainHandler mMainHandler;
@@ -218,10 +223,10 @@
private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
new RemoteCallbackList<>();
- private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
+ private final SparseArray<RemoteAccessibilityConnection> mGlobalInteractionConnections =
new SparseArray<>();
- private AccessibilityConnectionWrapper mPictureInPictureActionReplacingConnection;
+ private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection;
private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
@@ -453,6 +458,7 @@
// performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
// If the client is from a process that runs across users such as
// the system UI or the system we add it to the global state that
// is shared across users.
@@ -497,9 +503,14 @@
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
- // performs the current profile parent resolution..
+ // performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+ // Make sure the reported package is one the caller has access to.
+ event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked(
+ event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId));
+
// This method does nothing for a background user.
if (resolvedUserId == mCurrentUserId) {
if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
@@ -617,30 +628,38 @@
@Override
public int addAccessibilityInteractionConnection(IWindow windowToken,
- IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
+ IAccessibilityInteractionConnection connection, String packageName,
+ int userId) throws RemoteException {
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
// performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ final int resolvedUid = UserHandle.getUid(resolvedUserId, UserHandle.getCallingAppId());
+
+ // Make sure the reported package is one the caller has access to.
+ packageName = mSecurityPolicy.resolveValidReportedPackageLocked(
+ packageName, UserHandle.getCallingAppId(), resolvedUserId);
+
final int windowId = sNextWindowId++;
// If the window is from a process that runs across users such as
// the system UI or the system we add it to the global state that
// is shared across users.
if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
- AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
- windowId, connection, UserHandle.USER_ALL);
+ RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
+ windowId, connection, packageName, resolvedUid, UserHandle.USER_ALL);
wrapper.linkToDeath();
mGlobalInteractionConnections.put(windowId, wrapper);
mGlobalWindowTokens.put(windowId, windowToken.asBinder());
if (DEBUG) {
Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
- + " with windowId: " + windowId + " and token: " + windowToken.asBinder());
+ + " with windowId: " + windowId + " and token: "
+ + windowToken.asBinder());
}
} else {
- AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
- windowId, connection, resolvedUserId);
+ RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
+ windowId, connection, packageName, resolvedUid, resolvedUserId);
wrapper.linkToDeath();
UserState userState = getUserStateLocked(resolvedUserId);
userState.mInteractionConnections.put(windowId, wrapper);
@@ -693,13 +712,13 @@
private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
SparseArray<IBinder> windowTokens,
- SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
+ SparseArray<RemoteAccessibilityConnection> interactionConnections) {
final int count = windowTokens.size();
for (int i = 0; i < count; i++) {
if (windowTokens.valueAt(i) == windowToken) {
final int windowId = windowTokens.keyAt(i);
windowTokens.removeAt(i);
- AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
+ RemoteAccessibilityConnection wrapper = interactionConnections.get(windowId);
wrapper.unlinkToDeath();
interactionConnections.remove(windowId);
return windowId;
@@ -719,9 +738,9 @@
mPictureInPictureActionReplacingConnection = null;
}
if (connection != null) {
- AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+ RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID,
- connection, UserHandle.USER_ALL);
+ connection, "foo.bar.baz", Process.SYSTEM_UID, UserHandle.USER_ALL);
mPictureInPictureActionReplacingConnection = wrapper;
wrapper.linkToDeath();
}
@@ -2264,18 +2283,35 @@
}
}
- private class AccessibilityConnectionWrapper implements DeathRecipient {
+ class RemoteAccessibilityConnection implements DeathRecipient {
+ private final int mUid;
+ private final String mPackageName;
private final int mWindowId;
private final int mUserId;
private final IAccessibilityInteractionConnection mConnection;
- public AccessibilityConnectionWrapper(int windowId,
- IAccessibilityInteractionConnection connection, int userId) {
+ RemoteAccessibilityConnection(int windowId,
+ IAccessibilityInteractionConnection connection,
+ String packageName, int uid, int userId) {
mWindowId = windowId;
+ mPackageName = packageName;
+ mUid = uid;
mUserId = userId;
mConnection = connection;
}
+ public int getUid() {
+ return mUid;
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public IAccessibilityInteractionConnection getRemote() {
+ return mConnection;
+ }
+
public void linkToDeath() throws RemoteException {
mConnection.asBinder().linkToDeath(this, 0);
}
@@ -2532,11 +2568,13 @@
long accessibilityNodeId, int action, Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
long interrogatingTid) {
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
IBinder activityToken = null;
synchronized (mLock) {
connection = getConnectionLocked(resolvedWindowId);
- if (connection == null) return false;
+ if (connection == null) {
+ return false;
+ }
final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS)
|| (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
final AccessibilityWindowInfo a11yWindowInfo =
@@ -2548,7 +2586,7 @@
}
if ((a11yWindowInfo != null) && a11yWindowInfo.isInPictureInPictureMode()
&& (mPictureInPictureActionReplacingConnection != null) && !isA11yFocusAction) {
- connection = mPictureInPictureActionReplacingConnection.mConnection;
+ connection = mPictureInPictureActionReplacingConnection;
}
}
final int interrogatingPid = Binder.getCallingPid();
@@ -2563,8 +2601,9 @@
LocalServices.getService(ActivityManagerInternal.class)
.setFocusedActivity(activityToken);
}
- connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
- interactionId, callback, fetchFlags, interrogatingPid, interrogatingTid);
+ connection.mConnection.performAccessibilityAction(accessibilityNodeId, action,
+ arguments, interactionId, callback, fetchFlags, interrogatingPid,
+ interrogatingTid);
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
@@ -2577,17 +2616,17 @@
}
@Override
- public IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
+ public RemoteAccessibilityConnection getConnectionLocked(int windowId) {
if (DEBUG) {
Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
}
- AccessibilityManagerService.AccessibilityConnectionWrapper wrapper =
+ RemoteAccessibilityConnection connection =
mGlobalInteractionConnections.get(windowId);
- if (wrapper == null) {
- wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
+ if (connection == null) {
+ connection = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
}
- if (wrapper != null && wrapper.mConnection != null) {
- return wrapper.mConnection;
+ if (connection != null && connection.mConnection != null) {
+ return connection;
}
if (DEBUG) {
Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
@@ -2620,6 +2659,16 @@
}
}
+ private AppWidgetManagerInternal getAppWidgetManager() {
+ synchronized (mLock) {
+ if (mAppWidgetService == null
+ && mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
+ mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class);
+ }
+ return mAppWidgetService;
+ }
+ }
+
final class WindowsForAccessibilityCallback implements
WindowManagerInternal.WindowsForAccessibilityCallback {
@@ -2912,6 +2961,78 @@
}
}
+ private boolean isValidPackageForUid(String packageName, int uid) {
+ try {
+ return uid == mPackageManager.getPackageUidAsUser(
+ packageName, UserHandle.getUserId(uid));
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ String resolveValidReportedPackageLocked(CharSequence packageName, int appId, int userId) {
+ // Okay to pass no package
+ if (packageName == null) {
+ return null;
+ }
+ // The system gets to pass any package
+ if (appId == Process.SYSTEM_UID) {
+ return packageName.toString();
+ }
+ // Passing a package in your UID is fine
+ final String packageNameStr = packageName.toString();
+ final int resolvedUid = UserHandle.getUid(userId, appId);
+ if (isValidPackageForUid(packageNameStr, resolvedUid)) {
+ return packageName.toString();
+ }
+ // Appwidget hosts get to pass packages for widgets they host
+ final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
+ if (appWidgetManager != null && ArrayUtils.contains(appWidgetManager
+ .getHostedWidgetPackages(resolvedUid), packageNameStr)) {
+ return packageName.toString();
+ }
+ // Otherwise, set the package to the first one in the UID
+ final String[] packageNames = mPackageManager.getPackagesForUid(resolvedUid);
+ if (ArrayUtils.isEmpty(packageNames)) {
+ return null;
+ }
+ // Okay, the caller reported a package it does not have access to.
+ // Instead of crashing the caller for better backwards compatibility
+ // we report the first package in the UID. Since most of the time apps
+ // don't use shared user id, this will yield correct results and for
+ // the edge case of using a shared user id we may report the wrong
+ // package but this is fine since first, this is a cheating app and
+ // second there is no way to get the correct package anyway.
+ return packageNames[0];
+ }
+
+ String[] computeValidReportedPackages(int callingUid,
+ String targetPackage, int targetUid) {
+ if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
+ // Empty array means any package is Okay
+ return EmptyArray.STRING;
+ }
+ // IMPORTANT: The target package is already vetted to be in the target UID
+ String[] uidPackages = new String[]{targetPackage};
+ // Appwidget hosts get to pass packages for widgets they host
+ final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
+ if (appWidgetManager != null) {
+ final ArraySet<String> widgetPackages = appWidgetManager
+ .getHostedWidgetPackages(targetUid);
+ if (widgetPackages != null && !widgetPackages.isEmpty()) {
+ final String[] validPackages = new String[uidPackages.length
+ + widgetPackages.size()];
+ System.arraycopy(uidPackages, 0, validPackages, 0, uidPackages.length);
+ final int widgetPackageCount = widgetPackages.size();
+ for (int i = 0; i < widgetPackageCount; i++) {
+ validPackages[uidPackages.length + i] = widgetPackages.valueAt(i);
+ }
+ return validPackages;
+ }
+ }
+ return uidPackages;
+ }
+
public void clearWindowsLocked() {
List<WindowInfo> windows = Collections.emptyList();
final int activeWindowId = mActiveWindowId;
@@ -3338,7 +3459,7 @@
public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
new RemoteCallbackList<>();
- public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
+ public final SparseArray<RemoteAccessibilityConnection> mInteractionConnections =
new SparseArray<>();
public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
new file mode 100644
index 0000000..aad2ad19
--- /dev/null
+++ b/services/appwidget/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.appwidget",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/appwidget/Android.mk b/services/appwidget/Android.mk
deleted file mode 100644
index e9bab4a..0000000
--- a/services/appwidget/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.appwidget
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b446209..54cf726 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -32,6 +32,7 @@
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.appwidget.PendingHostUpdate;
import android.content.BroadcastReceiver;
@@ -100,6 +101,8 @@
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.widget.IRemoteViewsFactory;
@@ -107,6 +110,7 @@
import com.android.server.WidgetBackupProvider;
import com.android.server.policy.IconUtilities;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -259,6 +263,8 @@
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
registerOnCrossProfileProvidersChangedListener();
+
+ LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal());
}
private void computeMaximumWidgetBitmapMemory() {
@@ -4630,4 +4636,24 @@
}
}
}
+
+ private class AppWidgetManagerLocal extends AppWidgetManagerInternal {
+ @Override
+ public ArraySet<String> getHostedWidgetPackages(int uid) {
+ synchronized (mLock) {
+ ArraySet<String> widgetPackages = null;
+ final int widgetCount = mWidgets.size();
+ for (int i = 0; i < widgetCount; i++) {
+ final Widget widget = mWidgets.get(i);
+ if (widget.host.id.uid == uid) {
+ if (widgetPackages == null) {
+ widgetPackages = new ArraySet<>();
+ }
+ widgetPackages.add(widget.provider.id.componentName.getPackageName());
+ }
+ }
+ return widgetPackages;
+ }
+ }
+ }
}
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
new file mode 100644
index 0000000..2768c18
--- /dev/null
+++ b/services/autofill/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.autofill",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/autofill/Android.mk b/services/autofill/Android.mk
deleted file mode 100644
index a1f19fd..0000000
--- a/services/autofill/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.autofill
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index b2a0ce5..7bc63f0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -36,6 +36,7 @@
import android.content.pm.ServiceInfo;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
@@ -352,7 +353,7 @@
pruneAbandonedSessionsLocked();
final Session newSession = createSessionByTokenLocked(activityToken, uid, appCallbackToken,
- hasCallback, componentName);
+ hasCallback, componentName, flags);
if (newSession == null) {
return NO_SESSION;
}
@@ -453,7 +454,7 @@
private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid,
@NonNull IBinder appCallbackToken, boolean hasCallback,
- @NonNull ComponentName componentName) {
+ @NonNull ComponentName componentName, int flags) {
// use random ids so that one app cannot know that another app creates sessions
int sessionId;
int tries = 0;
@@ -471,7 +472,7 @@
final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock,
sessionId, uid, activityToken, appCallbackToken, hasCallback,
- mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName);
+ mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName, flags);
mSessions.put(newSession.id, newSession);
return newSession;
@@ -716,7 +717,8 @@
@Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
@Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
@Nullable ArrayList<AutofillId> detectedFieldIdsList,
- @Nullable ArrayList<Match> detectedMatchesList) {
+ @Nullable ArrayList<Match> detectedMatchesList,
+ @NonNull String appPackageName) {
synchronized (mLock) {
if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
@@ -727,6 +729,19 @@
detectedFieldIdsList.toArray(detectedFieldsIds);
detectedMatches = new Match[detectedMatchesList.size()];
detectedMatchesList.toArray(detectedMatches);
+
+ final int size = detectedMatchesList.size();
+ float totalScore = 0;
+ for (int i = 0; i < size; i++) {
+ totalScore += detectedMatches[i].getScore();
+ }
+ final int averageScore = (int) ((totalScore * 100) / size);
+ mMetricsLogger.write(
+ Helper.newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES,
+ appPackageName, getServicePackageName())
+ .setCounterValue(size)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE, averageScore));
+
}
mEventHistory.addEvent(new Event(Event.TYPE_CONTEXT_COMMITTED, null,
clientState, selectedDatasets, ignoredDatasets,
@@ -776,6 +791,11 @@
synchronized (mLock) {
if (isCalledByServiceLocked("setUserData", callingUid)) {
mUserData = userData;
+ // Log it
+ int numberFields = mUserData == null ? 0: mUserData.getRemoteIds().length;
+ mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED,
+ getServicePackageName(), null)
+ .setCounterValue(numberFields));
}
}
}
@@ -1013,10 +1033,12 @@
expiration = Long.MAX_VALUE;
}
mDisabledActivities.put(componentName, expiration);
- int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
- mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY,
- componentName.getPackageName(), getServicePackageName())
- .addTaggedData(MetricsEvent.FIELD_CLASS_NAME, componentName.getClassName())
+ final int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
+ // NOTE: not using Helper.newLogMaker() because we're setting the componentName instead
+ // of package name
+ mMetricsLogger.write(new LogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY)
+ .setComponentName(componentName)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, getServicePackageName())
.setCounterValue(intDuration));
}
}
@@ -1034,7 +1056,8 @@
if (expiration >= elapsedTime) return true;
// Restriction expired - clean it up.
if (sVerbose) {
- Slog.v(TAG, "Removing " + componentName.toShortString() + " from disabled list");
+ Slog.v(TAG, "Removing " + componentName.toShortString()
+ + " from disabled list");
}
mDisabledActivities.remove(componentName);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4e64afb..56f5f64 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -128,6 +128,9 @@
/** uid the session is for */
public final int uid;
+ /** Flags used to start the session */
+ public final int mFlags;
+
@GuardedBy("mLock")
@NonNull private IBinder mActivityToken;
@@ -441,8 +444,10 @@
@NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId,
@NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken,
@NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
- @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName) {
+ @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName,
+ int flags) {
id = sessionId;
+ mFlags = flags;
this.uid = uid;
mStartTime = SystemClock.elapsedRealtime();
mService = service;
@@ -456,7 +461,8 @@
mComponentName = componentName;
mClient = IAutoFillManagerClient.Stub.asInterface(client);
- writeLog(MetricsEvent.AUTOFILL_SESSION_STARTED);
+ mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
+ .addTaggedData(MetricsEvent.FIELD_FLAGS, flags));
}
/**
@@ -505,8 +511,9 @@
}
}
- // TODO(b/67867469): remove once feature is finished
- if (response.getFieldClassificationIds() != null && !mService.isFieldClassificationEnabled()) {
+ final AutofillId[] fieldClassificationIds = response.getFieldClassificationIds();
+ // TODO(b/67867469): remove once feature is finished (or use method from AFM to check)
+ if (fieldClassificationIds != null && !mService.isFieldClassificationEnabled()) {
Slog.w(TAG, "Ignoring " + response + " because field detection is disabled");
processNullResponseLocked(requestFlags);
return;
@@ -548,6 +555,10 @@
.setType(MetricsEvent.TYPE_SUCCESS)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
response.getDatasets() == null ? 0 : response.getDatasets().size());
+ if (fieldClassificationIds != null) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS,
+ fieldClassificationIds.length);
+ }
mMetricsLogger.write(log);
}
@@ -1106,7 +1117,7 @@
mService.logContextCommitted(id, mClientState, mSelectedDatasetIds, ignoredDatasets,
changedFieldIds, changedDatasetIds,
manuallyFilledFieldIds, manuallyFilledDatasetIds,
- detectedFieldIds, detectedMatches);
+ detectedFieldIds, detectedMatches, mComponentName.getPackageName());
}
/**
@@ -2115,6 +2126,7 @@
final String prefix2 = prefix + " ";
pw.print(prefix); pw.print("id: "); pw.println(id);
pw.print(prefix); pw.print("uid: "); pw.println(uid);
+ pw.print(prefix); pw.print("flags: "); pw.println(mFlags);
pw.print(prefix); pw.print("mComponentName: "); pw.println(mComponentName);
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("mStartTime: "); pw.println(mStartTime);
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
new file mode 100644
index 0000000..ef03d83
--- /dev/null
+++ b/services/backup/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.backup",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/backup/Android.mk b/services/backup/Android.mk
deleted file mode 100644
index 3e686d1..0000000
--- a/services/backup/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.backup
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
new file mode 100644
index 0000000..d2dac35
--- /dev/null
+++ b/services/companion/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.companion",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/companion/Android.mk b/services/companion/Android.mk
deleted file mode 100644
index be48761..0000000
--- a/services/companion/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.companion
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/Android.bp b/services/core/Android.bp
new file mode 100644
index 0000000..446c2a5
--- /dev/null
+++ b/services/core/Android.bp
@@ -0,0 +1,57 @@
+java_library_static {
+ name: "services.core",
+
+ aidl: {
+ include_dirs: [
+ "frameworks/native/aidl/binder",
+ "system/core/storaged/binder",
+ "system/netd/server/binder",
+ "system/vold/binder",
+ ],
+ },
+ srcs: [
+ "java/**/*.java",
+ ":netd_aidl",
+ ":netd_metrics_aidl",
+ ":installd_aidl",
+ ":storaged_aidl",
+ ":vold_aidl",
+ "java/com/android/server/EventLogTags.logtags",
+ "java/com/android/server/am/EventLogTags.logtags",
+ ],
+
+ libs: [
+ "services.net",
+ "android.hardware.light-V2.0-java",
+ "android.hardware.power-V1.0-java",
+ "android.hardware.tv.cec-V1.0-java",
+ "android.hidl.manager-V1.0-java",
+ ],
+
+ static_libs: [
+ "time_zone_distro",
+ "time_zone_distro_installer",
+ "android.hardware.health-V1.0-java",
+ "android.hardware.health-V2.0-java",
+ "android.hardware.weaver-V1.0-java",
+ "android.hardware.biometrics.fingerprint-V2.1-java",
+ "android.hardware.oemlock-V1.0-java",
+ "android.hardware.tetheroffload.control-V1.0-java",
+ "android.hardware.vibrator-V1.0-java",
+ "android.hardware.configstore-V1.0-java",
+ "android.hardware.contexthub-V1.0-java",
+ ],
+}
+
+java_genrule {
+ name: "services.core.priorityboosted",
+ srcs: [":services.core"],
+ tools: ["lockedregioncodeinjection"],
+ cmd: "$(location lockedregioncodeinjection) " +
+ " --targets \"Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/wm/WindowHashMap;\" " +
+ " --pre \"com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection\" " +
+ " --post \"com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection\" " +
+ " -o $(out) " +
+ " -i $(in)",
+ out: ["services.core.priorityboosted.jar"],
+}
diff --git a/services/core/Android.mk b/services/core/Android.mk
deleted file mode 100644
index 3d81baf..0000000
--- a/services/core/Android.mk
+++ /dev/null
@@ -1,72 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.core
-
-LOCAL_AIDL_INCLUDES := \
- frameworks/native/aidl/binder \
- system/core/storaged/binder \
- system/netd/server/binder \
- system/vold/binder
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java) \
- java/com/android/server/EventLogTags.logtags \
- java/com/android/server/am/EventLogTags.logtags \
- ../../../../system/core/storaged/binder/android/os/IStoraged.aidl \
- ../../../../system/netd/server/binder/android/net/INetd.aidl \
- ../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
- ../../../../system/vold/binder/android/os/IVold.aidl \
- ../../../../system/vold/binder/android/os/IVoldListener.aidl \
- ../../../../system/vold/binder/android/os/IVoldTaskListener.aidl \
- ../../../native/cmds/installd/binder/android/os/IInstalld.aidl \
-
-LOCAL_AIDL_INCLUDES += \
- system/netd/server/binder
-
-LOCAL_JAVA_LIBRARIES := \
- services.net \
- android.hardware.light-V2.0-java \
- android.hardware.power-V1.0-java \
- android.hardware.tv.cec-V1.0-java \
- android.hidl.manager-V1.0-java
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- time_zone_distro \
- time_zone_distro_installer \
- android.hidl.base-V1.0-java \
- android.hardware.health-V1.0-java \
- android.hardware.health-V2.0-java \
- android.hardware.weaver-V1.0-java \
- android.hardware.biometrics.fingerprint-V2.1-java \
- android.hardware.oemlock-V1.0-java \
- android.hardware.tetheroffload.control-V1.0-java \
- android.hardware.vibrator-V1.0-java \
- android.hardware.configstore-V1.0-java \
- android.hardware.contexthub-V1.0-java
-
-ifneq ($(INCREMENTAL_BUILDS),)
- LOCAL_PROGUARD_ENABLED := disabled
- LOCAL_JACK_ENABLED := incremental
-endif
-
-LOCAL_JACK_FLAGS := \
- -D jack.transformations.boost-locked-region-priority=true \
- -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService,com.android.server.wm.WindowHashMap \
- -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection,com.android.server.wm.WindowManagerService\#boostPriorityForLockedSection \
- -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection,com.android.server.wm.WindowManagerService\#resetPriorityAfterLockedSection
-
-LOCAL_JAR_PROCESSOR := lockedregioncodeinjection
-# Use = instead of := to delay evaluation of ${in} and ${out}
-LOCAL_JAR_PROCESSOR_ARGS = \
- --targets \
- "Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/wm/WindowHashMap;" \
- --pre \
- "com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection" \
- --post \
- "com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection" \
- -o ${out} \
- -i ${in}
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/AnimationThread.java b/services/core/java/com/android/server/AnimationThread.java
index 08392b0..c86042b 100644
--- a/services/core/java/com/android/server/AnimationThread.java
+++ b/services/core/java/com/android/server/AnimationThread.java
@@ -22,8 +22,8 @@
import android.os.Trace;
/**
- * Thread for handling all window animations, or anything that's directly impacting animations like
- * starting windows or traversals.
+ * Thread for handling all legacy window animations, or anything that's directly impacting
+ * animations like starting windows or traversals.
*/
public final class AnimationThread extends ServiceThread {
private static AnimationThread sInstance;
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 763a4e4..d9713a5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1628,7 +1628,7 @@
//Do enable request
try {
- if (mQuietEnable) {
+ if (!mQuietEnable) {
if (!mBluetooth.enable()) {
Slog.e(TAG, "IBluetooth.enable() returned false");
}
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index a97b93c..aed49e0 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -105,7 +105,8 @@
/**
* TODO(b/64750076): Capture information necessary for dump and
* {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
- * around */
+ * around
+ */
private ActivityStarter mLastStarter;
ActivityStartController(ActivityManagerService service) {
@@ -130,10 +131,16 @@
* considered invalid and no longer modified or used.
*/
ActivityStarter obtainStarter(Intent intent, String reason) {
- final ActivityStarter starter = mFactory.obtainStarter();
- mLastStarter = starter;
+ return mFactory.obtain().setIntent(intent).setReason(reason);
+ }
- return starter.setIntent(intent).setReason(reason);
+ void onExecutionComplete(ActivityStarter starter) {
+ if (mLastStarter == null) {
+ mLastStarter = mFactory.obtain();
+ }
+
+ mLastStarter.set(starter);
+ mFactory.recycle(starter);
}
/**
@@ -142,6 +149,10 @@
*/
void postStartActivityProcessingForLastStarter(ActivityRecord r, int result,
ActivityStack targetStack) {
+ if (mLastStarter == null) {
+ return;
+ }
+
mLastStarter.postStartActivityProcessing(r, result, targetStack);
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 10fb6e2a..69cc3c7 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -102,6 +102,7 @@
import android.service.voice.IVoiceInteractionSession;
import android.text.TextUtils;
import android.util.EventLog;
+import android.util.Pools.SynchronizedPool;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -131,7 +132,6 @@
private final ActivityManagerService mService;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
-
private final ActivityStartController mController;
// Share state variable among methods when starting an activity.
@@ -209,18 +209,34 @@
* this instance.
* @return an {@link ActivityStarter}
*/
- ActivityStarter obtainStarter();
+ ActivityStarter obtain();
+
+ /**
+ * Recycles a starter for reuse.
+ */
+ void recycle(ActivityStarter starter);
}
/**
* Default implementation of {@link StarterFactory}.
*/
static class DefaultFactory implements Factory {
+ /**
+ * The maximum count of starters that should be active at one time:
+ * 1. last ran starter (for logging and post activity processing)
+ * 2. current running starter
+ * 3. starter from re-entry in (2)
+ */
+ private final int MAX_STARTER_COUNT = 3;
+
private ActivityStartController mController;
private ActivityManagerService mService;
private ActivityStackSupervisor mSupervisor;
private ActivityStartInterceptor mInterceptor;
+ private SynchronizedPool<ActivityStarter> mStarterPool =
+ new SynchronizedPool<>(MAX_STARTER_COUNT);
+
DefaultFactory(ActivityManagerService service,
ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
mService = service;
@@ -234,9 +250,20 @@
}
@Override
- public ActivityStarter obtainStarter() {
- // TODO(b/64750076): Investigate recycling instances to reduce object creation overhead.
- return new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
+ public ActivityStarter obtain() {
+ ActivityStarter starter = mStarterPool.acquire();
+
+ if (starter == null) {
+ starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
+ }
+
+ return starter;
+ }
+
+ @Override
+ public void recycle(ActivityStarter starter) {
+ starter.reset(true /* clearRequest*/);
+ mStarterPool.release(starter);
}
}
@@ -289,6 +316,76 @@
* {@see ActivityStarter#startActivityMayWait}.
*/
boolean mayWait;
+
+ /**
+ * Sets values back to the initial state, clearing any held references.
+ */
+ void reset() {
+ caller = null;
+ intent = null;
+ ephemeralIntent = null;
+ resolvedType = null;
+ activityInfo = null;
+ resolveInfo = null;
+ voiceSession = null;
+ voiceInteractor = null;
+ resultTo = null;
+ resultWho = null;
+ requestCode = 0;
+ callingPid = 0;
+ callingUid = 0;
+ callingPackage = null;
+ realCallingPid = 0;
+ realCallingUid = 0;
+ startFlags = 0;
+ activityOptions = null;
+ ignoreTargetSecurity = false;
+ componentSpecified = false;
+ outActivity = null;
+ inTask = null;
+ reason = null;
+ profilerInfo = null;
+ globalConfig = null;
+ waitOptions = null;
+ userId = 0;
+ waitResult = null;
+ mayWait = false;
+ }
+
+ /**
+ * Adopts all values from passed in request.
+ */
+ void set(Request request) {
+ caller = request.caller;
+ intent = request.intent;
+ ephemeralIntent = request.ephemeralIntent;
+ resolvedType = request.resolvedType;
+ activityInfo = request.activityInfo;
+ resolveInfo = request.resolveInfo;
+ voiceSession = request.voiceSession;
+ voiceInteractor = request.voiceInteractor;
+ resultTo = request.resultTo;
+ resultWho = request.resultWho;
+ requestCode = request.requestCode;
+ callingPid = request.callingPid;
+ callingUid = request.callingUid;
+ callingPackage = request.callingPackage;
+ realCallingPid = request.realCallingPid;
+ realCallingUid = request.realCallingUid;
+ startFlags = request.startFlags;
+ activityOptions = request.activityOptions;
+ ignoreTargetSecurity = request.ignoreTargetSecurity;
+ componentSpecified = request.componentSpecified;
+ outActivity = request.outActivity;
+ inTask = request.inTask;
+ reason = request.reason;
+ profilerInfo = request.profilerInfo;
+ globalConfig = request.globalConfig;
+ waitOptions = request.waitOptions;
+ userId = request.userId;
+ waitResult = request.waitResult;
+ mayWait = request.mayWait;
+ }
}
ActivityStarter(ActivityStartController controller, ActivityManagerService service,
@@ -297,6 +394,52 @@
mService = service;
mSupervisor = supervisor;
mInterceptor = interceptor;
+ reset(true);
+ }
+
+ /**
+ * Effectively duplicates the starter passed in. All state and request values will be
+ * mirrored.
+ * @param starter
+ */
+ void set(ActivityStarter starter) {
+ mStartActivity = starter.mStartActivity;
+ mIntent = starter.mIntent;
+ mCallingUid = starter.mCallingUid;
+ mOptions = starter.mOptions;
+
+ mLaunchTaskBehind = starter.mLaunchTaskBehind;
+ mLaunchFlags = starter.mLaunchFlags;
+ mLaunchMode = starter.mLaunchMode;
+
+ mLaunchBounds.set(starter.mLaunchBounds);
+
+ mNotTop = starter.mNotTop;
+ mDoResume = starter.mDoResume;
+ mStartFlags = starter.mStartFlags;
+ mSourceRecord = starter.mSourceRecord;
+ mPreferredDisplayId = starter.mPreferredDisplayId;
+
+ mInTask = starter.mInTask;
+ mAddingToTask = starter.mAddingToTask;
+ mReuseTask = starter.mReuseTask;
+
+ mNewTaskInfo = starter.mNewTaskInfo;
+ mNewTaskIntent = starter.mNewTaskIntent;
+ mSourceStack = starter.mSourceStack;
+
+ mTargetStack = starter.mTargetStack;
+ mMovedToFront = starter.mMovedToFront;
+ mNoAnimation = starter.mNoAnimation;
+ mKeepCurTransition = starter.mKeepCurTransition;
+ mAvoidMoveToFront = starter.mAvoidMoveToFront;
+
+ mVoiceSession = starter.mVoiceSession;
+ mVoiceInteractor = starter.mVoiceInteractor;
+
+ mIntentDelivered = starter.mIntentDelivered;
+
+ mRequest.set(starter.mRequest);
}
ActivityRecord getStartActivity() {
@@ -314,25 +457,47 @@
* @return The starter result.
*/
int execute() {
- // TODO(b/64750076): Look into passing request directly to these methods to allow
- // for transactional diffs and preprocessing.
- if (mRequest.mayWait) {
- return startActivityMayWait(mRequest.caller, mRequest.callingUid,
- mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
- mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
- mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
- mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
- mRequest.waitOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
- mRequest.inTask, mRequest.reason);
- } else {
- return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
- mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
- mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
- mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
- mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
- mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
- mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
- mRequest.outActivity, mRequest.inTask, mRequest.reason);
+ try {
+ // TODO(b/64750076): Look into passing request directly to these methods to allow
+ // for transactional diffs and preprocessing.
+ if (mRequest.mayWait) {
+ return startActivityMayWait(mRequest.caller, mRequest.callingUid,
+ mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
+ mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
+ mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
+ mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
+ mRequest.waitOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
+ mRequest.inTask, mRequest.reason);
+ } else {
+ return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
+ mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
+ mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
+ mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
+ mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
+ mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
+ mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
+ mRequest.outActivity, mRequest.inTask, mRequest.reason);
+ }
+ } finally {
+ onExecutionComplete();
+ }
+ }
+
+ /**
+ * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
+ * Note that this method is called internally as well as part of {@link #startActivity}.
+ *
+ * @return The start result.
+ */
+ int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+ IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+ int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
+ ActivityRecord[] outActivity) {
+ try {
+ return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
+ doResume, options, inTask, outActivity);
+ } finally {
+ onExecutionComplete();
}
}
@@ -370,6 +535,14 @@
return result != START_ABORTED ? result : START_SUCCESS;
}
+ /**
+ * Called when execution is complete. Sets state indicating completion and proceeds with
+ * recycling if appropriate.
+ */
+ private void onExecutionComplete() {
+ mController.onExecutionComplete(this);
+ }
+
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
@@ -652,7 +825,7 @@
mController.doPendingActivityLaunches(false);
- return startResolvedActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
+ return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, options, inTask, outActivity);
}
@@ -925,16 +1098,10 @@
}
}
- /**
- * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
- * Note that this method is called internally as well as part of {@link #startActivity}.
- *
- * @return The start result.
- */
- int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
- ActivityRecord[] outActivity) {
+ private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+ IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+ int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
+ ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
@@ -1190,9 +1357,57 @@
return START_SUCCESS;
}
+ /**
+ * Resets the {@link ActivityStarter} state.
+ * @param clearRequest whether the request should be reset to default values.
+ */
+ void reset(boolean clearRequest) {
+ mStartActivity = null;
+ mIntent = null;
+ mCallingUid = -1;
+ mOptions = null;
+
+ mLaunchTaskBehind = false;
+ mLaunchFlags = 0;
+ mLaunchMode = INVALID_LAUNCH_MODE;
+
+ mLaunchBounds.setEmpty();
+
+ mNotTop = null;
+ mDoResume = false;
+ mStartFlags = 0;
+ mSourceRecord = null;
+ mPreferredDisplayId = INVALID_DISPLAY;
+
+ mInTask = null;
+ mAddingToTask = false;
+ mReuseTask = null;
+
+ mNewTaskInfo = null;
+ mNewTaskIntent = null;
+ mSourceStack = null;
+
+ mTargetStack = null;
+ mMovedToFront = false;
+ mNoAnimation = false;
+ mKeepCurTransition = false;
+ mAvoidMoveToFront = false;
+
+ mVoiceSession = null;
+ mVoiceInteractor = null;
+
+ mIntentDelivered = false;
+
+ if (clearRequest) {
+ mRequest.reset();
+ }
+ }
+
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+ reset(false /* clearRequest */);
+
mStartActivity = r;
mIntent = r.intent;
mOptions = options;
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
index 28c3585..bd2e96e 100644
--- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -51,6 +51,7 @@
// Information about the current status of the default network.
@GuardedBy("this")
private DefaultNetworkEvent mCurrentDefaultNetwork;
+ // True if the current default network has been validated.
@GuardedBy("this")
private boolean mIsCurrentlyValid;
@GuardedBy("this")
@@ -71,6 +72,8 @@
printEvent(localTimeMs, pw, ev);
}
mCurrentDefaultNetwork.updateDuration(timeMs);
+ // When printing default network events for bug reports, update validation time
+ // and refresh the last validation timestmap for future validation time updates.
if (mIsCurrentlyValid) {
updateValidationTime(timeMs);
mLastValidationTimeMs = timeMs;
@@ -92,11 +95,13 @@
}
public synchronized void logDefaultNetworkValidity(long timeMs, boolean isValid) {
+ // Transition from valid to invalid: update validity duration since last update
if (!isValid && mIsCurrentlyValid) {
mIsCurrentlyValid = false;
updateValidationTime(timeMs);
}
+ // Transition from invalid to valid: simply mark the validation timestamp.
if (isValid && !mIsCurrentlyValid) {
mIsCurrentlyValid = true;
mLastValidationTimeMs = timeMs;
@@ -114,6 +119,9 @@
}
private void logCurrentDefaultNetwork(long timeMs, NetworkAgentInfo oldNai) {
+ if (mIsCurrentlyValid) {
+ updateValidationTime(timeMs);
+ }
DefaultNetworkEvent ev = mCurrentDefaultNetwork;
ev.updateDuration(timeMs);
ev.previousTransports = mLastTransports;
@@ -122,7 +130,6 @@
// The system acquired a new default network.
fillLinkInfo(ev, oldNai);
ev.finalScore = oldNai.getCurrentScore();
- ev.validatedMs = ev.durationMs;
}
// Only change transport of the previous default network if the event currently logged
// corresponds to an existing default network, and not to the absence of a default network.
@@ -143,9 +150,10 @@
fillLinkInfo(ev, newNai);
ev.initialScore = newNai.getCurrentScore();
if (newNai.lastValidated) {
- mIsCurrentlyValid = true;
- mLastValidationTimeMs = timeMs;
+ logDefaultNetworkValidity(timeMs, true);
}
+ } else {
+ mIsCurrentlyValid = false;
}
mCurrentDefaultNetwork = ev;
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 19a74d7..c1bfa47 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -76,6 +76,7 @@
import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.wm.WindowManagerInternal;
+import com.android.server.wm.SurfaceAnimationThread;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -292,6 +293,8 @@
Process.THREAD_GROUP_TOP_APP);
Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
Process.THREAD_GROUP_TOP_APP);
+ Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
+ Process.THREAD_GROUP_TOP_APP);
}
@Override
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 3f014b5..f2a1c47 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1721,16 +1721,29 @@
// If the app is in a non-active standby bucket, make sure we've waited
// an appropriate amount of time since the last invocation
- if (mHeartbeat < mNextBucketHeartbeat[job.getStandbyBucket()]) {
- // TODO: log/trace that we're deferring the job due to bucketing if we hit this
- if (job.getWhenStandbyDeferred() == 0) {
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
- + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+ final int bucket = job.getStandbyBucket();
+ if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
+ // Only skip this job if it's still waiting for the end of its (initial) nominal
+ // bucket interval. Once it's waited that long, we let it go ahead and clear.
+ // The final (NEVER) bucket is special; we never age those apps' jobs into
+ // runnability.
+ if (bucket >= mConstants.STANDBY_BEATS.length
+ || (mHeartbeat < job.getBaseHeartbeat() + mConstants.STANDBY_BEATS[bucket])) {
+ // TODO: log/trace that we're deferring the job due to bucketing if we hit this
+ if (job.getWhenStandbyDeferred() == 0) {
+ if (DEBUG_STANDBY) {
+ Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
+ + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+ }
+ job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
}
- job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
+ return false;
+ } else {
+ if (DEBUG_STANDBY) {
+ Slog.v(TAG, "Bucket deferred job aged into runnability at "
+ + mHeartbeat + " : " + job);
+ }
}
- return false;
}
// The expensive check last: validate that the defined package+service is
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e0f3ec7..5dfb48a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12884,14 +12884,13 @@
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return null;
}
- // writer
- synchronized (mPackages) {
- if (!isExternalMediaAvailable()) {
+ if (!isExternalMediaAvailable()) {
// If the external storage is no longer mounted at this point,
// the caller may not have been able to delete all of this
// packages files and can not delete any more. Bail.
- return null;
- }
+ return null;
+ }
+ synchronized (mPackages) {
final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
if (lastPackage != null) {
pkgs.remove(lastPackage);
diff --git a/services/core/java/com/android/server/timezone/ClockHelper.java b/services/core/java/com/android/server/timezone/ClockHelper.java
deleted file mode 100644
index 353728a..0000000
--- a/services/core/java/com/android/server/timezone/ClockHelper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.timezone;
-
-/**
- * An easy-to-mock interface for obtaining a monotonically increasing time value in milliseconds.
- */
-interface ClockHelper {
-
- long currentTimestamp();
-}
diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java
index 1c54320..c362c80 100644
--- a/services/core/java/com/android/server/timezone/PackageTracker.java
+++ b/services/core/java/com/android/server/timezone/PackageTracker.java
@@ -22,11 +22,14 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
+import android.os.FileUtils;
+import android.os.SystemClock;
import android.provider.TimeZoneRulesDataContract;
import android.util.Slog;
import java.io.File;
import java.io.PrintWriter;
+import java.time.Clock;
/**
* Monitors the installed applications associated with time zone updates. If the app packages are
@@ -58,7 +61,7 @@
private final IntentHelper mIntentHelper;
private final ConfigHelper mConfigHelper;
private final PackageStatusStorage mPackageStatusStorage;
- private final ClockHelper mClockHelper;
+ private final Clock mElapsedRealtimeClock;
// False if tracking is disabled.
private boolean mTrackingEnabled;
@@ -91,15 +94,15 @@
/** Creates the {@link PackageTracker} for normal use. */
static PackageTracker create(Context context) {
+ Clock elapsedRealtimeClock = SystemClock.elapsedRealtimeClock();
PackageTrackerHelperImpl helperImpl = new PackageTrackerHelperImpl(context);
- // TODO(nfuller): Switch to FileUtils.createDir() when available. http://b/31008728
- File storageDir = new File(Environment.getDataSystemDirectory(), "timezone");
+ File storageDir = FileUtils.createDir(Environment.getDataSystemDirectory(), "timezone");
if (!storageDir.exists()) {
storageDir.mkdir();
}
return new PackageTracker(
- helperImpl /* clock */,
+ elapsedRealtimeClock /* elapsedRealtimeClock */,
helperImpl /* configHelper */,
helperImpl /* packageManagerHelper */,
new PackageStatusStorage(storageDir),
@@ -107,10 +110,10 @@
}
// A constructor that can be used by tests to supply mocked / faked dependencies.
- PackageTracker(ClockHelper clockHelper, ConfigHelper configHelper,
+ PackageTracker(Clock elapsedRealtimeClock, ConfigHelper configHelper,
PackageManagerHelper packageManagerHelper, PackageStatusStorage packageStatusStorage,
IntentHelper intentHelper) {
- mClockHelper = clockHelper;
+ mElapsedRealtimeClock = elapsedRealtimeClock;
mConfigHelper = configHelper;
mPackageManagerHelper = packageManagerHelper;
mPackageStatusStorage = packageStatusStorage;
@@ -425,7 +428,7 @@
}
private void setCheckInProgress() {
- mLastTriggerTimestamp = mClockHelper.currentTimestamp();
+ mLastTriggerTimestamp = mElapsedRealtimeClock.millis();
}
private void setCheckComplete() {
@@ -441,7 +444,7 @@
return false;
}
// Risk of overflow, but highly unlikely given the implementation and not problematic.
- return mClockHelper.currentTimestamp() > mLastTriggerTimestamp + mCheckTimeAllowedMillis;
+ return mElapsedRealtimeClock.millis() > mLastTriggerTimestamp + mCheckTimeAllowedMillis;
}
private PackageVersions lookupInstalledPackageVersions() {
diff --git a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
index 6a330e6..5f90be1 100644
--- a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
@@ -25,7 +25,6 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Slog;
@@ -34,7 +33,7 @@
/**
* A single class that implements multiple helper interfaces for use by {@link PackageTracker}.
*/
-final class PackageTrackerHelperImpl implements ClockHelper, ConfigHelper, PackageManagerHelper {
+final class PackageTrackerHelperImpl implements ConfigHelper, PackageManagerHelper {
private static final String TAG = "PackageTrackerHelperImpl";
@@ -74,13 +73,6 @@
}
@Override
- public long currentTimestamp() {
- // Use of elapsedRealtime() because this is in-memory state and elapsedRealtime() shouldn't
- // change if the system clock changes.
- return SystemClock.elapsedRealtime();
- }
-
- @Override
public long getInstalledPackageVersion(String packageName)
throws PackageManager.NameNotFoundException {
int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
index 0cf61c0..e8a401e 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
@@ -16,6 +16,8 @@
package com.android.server.timezone;
+import com.android.internal.util.DumpUtils;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
@@ -46,15 +48,7 @@
@Override
public boolean checkDumpPermission(String tag, PrintWriter pw) {
- // TODO(nfuller): Switch to DumpUtils.checkDumpPermission() when it is available in AOSP.
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump LocationManagerService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return false;
- }
- return true;
+ return DumpUtils.checkDumpPermission(mContext, tag, pw);
}
@Override
diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java
new file mode 100644
index 0000000..84d47b4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AnimationAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.annotation.ColorInt;
+import android.graphics.Point;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+/**
+ * Interface that describes an animation and bridges the animation start to the component
+ * responsible for running the animation.
+ */
+interface AnimationAdapter {
+
+ /**
+ * @return Whether we should detach the wallpaper during the animation.
+ * @see Animation#setDetachWallpaper
+ */
+ boolean getDetachWallpaper();
+
+ /**
+ * @return The background color behind the animation.
+ */
+ @ColorInt int getBackgroundColor();
+
+ /**
+ * Requests to start the animation.
+ *
+ * @param animationLeash The surface to run the animation on. See {@link SurfaceAnimator} for an
+ * overview of the mechanism. This surface needs to be released by the
+ * component running the animation after {@code finishCallback} has been
+ * invoked, or after the animation was cancelled.
+ * @param t The Transaction to apply the initial frame of the animation.
+ * @param finishCallback The callback to be invoked when the animation has finished.
+ */
+ void startAnimation(SurfaceControl animationLeash, Transaction t,
+ OnAnimationFinishedCallback finishCallback);
+
+ /**
+ * Called when the animation that was started with {@link #startAnimation} was cancelled by the
+ * window manager.
+ *
+ * @param animationLeash The leash passed to {@link #startAnimation}.
+ */
+ void onAnimationCancelled(SurfaceControl animationLeash);
+
+ /**
+ * @return The approximate duration of the animation, in milliseconds.
+ */
+ long getDurationHint();
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 91cad46..eda8fec 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1766,8 +1766,8 @@
updateBounds();
}
- void getContentRect(Rect out) {
- out.set(mDisplayFrames.mContent);
+ void getStableRect(Rect out) {
+ out.set(mDisplayFrames.mStable);
}
TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 7e29a3a..88b7a11 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -390,12 +390,13 @@
}
}
- final boolean inPositioning = (mService.mTaskPositioner != null);
+ final boolean inPositioning = mService.mTaskPositioningController.isPositioningLocked();
if (inPositioning) {
if (DEBUG_TASK_POSITIONING) {
Log.d(TAG_WM, "Inserting window handle for repositioning");
}
- final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle;
+ final InputWindowHandle dragWindowHandle =
+ mService.mTaskPositioningController.getDragWindowHandleLocked();
if (dragWindowHandle != null) {
addInputWindowHandle(dragWindowHandle);
} else {
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
new file mode 100644
index 0000000..5fe4565
--- /dev/null
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Point;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+/**
+ * Animation that can be executed without holding the window manager lock. See
+ * {@link SurfaceAnimationRunner}.
+ */
+class LocalAnimationAdapter implements AnimationAdapter {
+
+ private final AnimationSpec mSpec;
+ private final SurfaceAnimationRunner mAnimator;
+
+ LocalAnimationAdapter(AnimationSpec spec, SurfaceAnimationRunner animator) {
+ mSpec = spec;
+ mAnimator = animator;
+ }
+
+ @Override
+ public boolean getDetachWallpaper() {
+ return mSpec.getDetachWallpaper();
+ }
+
+ @Override
+ public int getBackgroundColor() {
+ return mSpec.getBackgroundColor();
+ }
+
+ @Override
+ public void startAnimation(SurfaceControl animationLeash, Transaction t,
+ OnAnimationFinishedCallback finishCallback) {
+ mAnimator.startAnimation(mSpec, animationLeash, t,
+ () -> finishCallback.onAnimationFinished(this));
+ }
+
+ @Override
+ public void onAnimationCancelled(SurfaceControl animationLeash) {
+ mAnimator.onAnimationCancelled(animationLeash);
+ }
+
+ @Override
+ public long getDurationHint() {
+ return mSpec.getDuration();
+ }
+
+ /**
+ * Describes how to apply an animation.
+ */
+ interface AnimationSpec {
+
+ /**
+ * @see AnimationAdapter#getDetachWallpaper
+ */
+ default boolean getDetachWallpaper() {
+ return false;
+ }
+
+ /**
+ * @see AnimationAdapter#getBackgroundColor
+ */
+ default int getBackgroundColor() {
+ return 0;
+ }
+
+ /**
+ * @return The duration of the animation.
+ */
+ long getDuration();
+
+ /**
+ * Called when the spec needs to apply the current animation state to the leash.
+ *
+ * @param t The transaction to use to apply a transform.
+ * @param leash The leash to apply the state to.
+ * @param currentPlayTime The current time of the animation.
+ */
+ void apply(Transaction t, SurfaceControl leash, long currentPlayTime);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 63eea10..192d6c8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -368,7 +368,7 @@
long ident = Binder.clearCallingIdentity();
try {
- return mService.startMovingTask(window, startX, startY);
+ return mService.mTaskPositioningController.startMovingTask(window, startX, startY);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
new file mode 100644
index 0000000..5bc2722
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.view.Choreographer.CALLBACK_TRAVERSAL;
+import static android.view.Choreographer.getSfInstance;
+
+import android.animation.AnimationHandler;
+import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.view.Choreographer;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Transformation;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.server.AnimationThread;
+import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+
+/**
+ * Class to run animations without holding the window manager lock.
+ */
+class SurfaceAnimationRunner {
+
+ private final Object mLock = new Object();
+
+ @VisibleForTesting
+ Choreographer mChoreographer;
+
+ private final Runnable mApplyTransactionRunnable = this::applyTransaction;
+ private final AnimationHandler mAnimationHandler;
+ private final Transaction mFrameTransaction;
+ private boolean mApplyScheduled;
+
+ @GuardedBy("mLock")
+ @VisibleForTesting
+ final ArrayMap<SurfaceControl, RunningAnimation> mPendingAnimations = new ArrayMap<>();
+
+ @GuardedBy("mLock")
+ @VisibleForTesting
+ final ArrayMap<SurfaceControl, ValueAnimator> mRunningAnimations = new ArrayMap<>();
+
+ SurfaceAnimationRunner() {
+ this(null /* callbackProvider */, new Transaction());
+ }
+
+ @VisibleForTesting
+ SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider,
+ Transaction frameTransaction) {
+ SurfaceAnimationThread.getHandler().runWithScissors(() -> mChoreographer = getSfInstance(),
+ 0 /* timeout */);
+ mFrameTransaction = frameTransaction;
+ mAnimationHandler = new AnimationHandler();
+ mAnimationHandler.setProvider(callbackProvider != null
+ ? callbackProvider
+ : new SfVsyncFrameCallbackProvider(mChoreographer));
+ }
+
+ void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
+ Runnable finishCallback) {
+ synchronized (mLock) {
+ final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
+ finishCallback);
+ mPendingAnimations.put(animationLeash, runningAnim);
+ mChoreographer.postFrameCallback(this::stepAnimation);
+
+ // Some animations (e.g. move animations) require the initial transform to be applied
+ // immediately.
+ applyTransformation(runningAnim, t, 0 /* currentPlayTime */);
+ }
+ }
+
+ void onAnimationCancelled(SurfaceControl leash) {
+ synchronized (mLock) {
+ if (mPendingAnimations.containsKey(leash)) {
+ mPendingAnimations.remove(leash);
+ // TODO: Releasing the leash is problematic if reparenting hasn't happened yet.
+ // Fix with transaction
+ //leash.release();
+ return;
+ }
+ final ValueAnimator anim = mRunningAnimations.get(leash);
+ if (anim != null) {
+ mRunningAnimations.remove(leash);
+ SurfaceAnimationThread.getHandler().post(() -> {
+ anim.cancel();
+ applyTransaction();
+ //leash.release();
+ });
+ }
+ }
+ }
+
+ private void startPendingAnimationsLocked() {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ startAnimationLocked(mPendingAnimations.valueAt(i));
+ }
+ mPendingAnimations.clear();
+ }
+
+ private void startAnimationLocked(RunningAnimation a) {
+ final ValueAnimator result = new SfValueAnimator();
+
+ // Animation length is already expected to be scaled.
+ result.overrideDurationScale(1.0f);
+ result.setDuration(a.animSpec.getDuration());
+ result.addUpdateListener(animation -> {
+ applyTransformation(a, mFrameTransaction, result.getCurrentPlayTime());
+
+ // Transaction will be applied in the commit phase.
+ scheduleApplyTransaction();
+ });
+ result.addListener(new AnimatorListenerAdapter() {
+
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mFrameTransaction.show(a.leash);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ synchronized (mLock) {
+ mRunningAnimations.remove(a.leash);
+ }
+ if (!mCancelled) {
+ // Post on other thread that we can push final state without jank.
+ AnimationThread.getHandler().post(() -> {
+ a.finishCallback.run();
+
+ // Make sure to release the leash after finishCallback has been invoked such
+ // that reparenting is done already when releasing the leash.
+ a.leash.release();
+ });
+ }
+ }
+ });
+ result.start();
+ mRunningAnimations.put(a.leash, result);
+ }
+
+ private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
+ a.animSpec.apply(t, a.leash, currentPlayTime);
+ }
+
+ private void stepAnimation(long frameTimeNanos) {
+ synchronized (mLock) {
+ startPendingAnimationsLocked();
+ }
+ }
+
+ private void scheduleApplyTransaction() {
+ if (!mApplyScheduled) {
+ mChoreographer.postCallback(CALLBACK_TRAVERSAL, mApplyTransactionRunnable,
+ null /* token */);
+ mApplyScheduled = true;
+ }
+ }
+
+ private void applyTransaction() {
+ mFrameTransaction.apply();
+ mApplyScheduled = false;
+ }
+
+ private static final class RunningAnimation {
+ final AnimationSpec animSpec;
+ final SurfaceControl leash;
+ final Runnable finishCallback;
+
+ RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
+ this.animSpec = animSpec;
+ this.leash = leash;
+ this.finishCallback = finishCallback;
+ }
+ }
+
+ /**
+ * Value animator that uses sf-vsync signal to tick.
+ */
+ private class SfValueAnimator extends ValueAnimator {
+
+ SfValueAnimator() {
+ setFloatValues(0f, 1f);
+ }
+
+ @Override
+ public AnimationHandler getAnimationHandler() {
+ return mAnimationHandler;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationThread.java b/services/core/java/com/android/server/wm/SurfaceAnimationThread.java
new file mode 100644
index 0000000..0d3afc0
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationThread.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+
+import android.os.Handler;
+import android.os.Trace;
+
+import com.android.server.ServiceThread;
+
+/**
+ * Thread for running {@link SurfaceAnimationRunner} that does not hold the window manager lock.
+ */
+public final class SurfaceAnimationThread extends ServiceThread {
+ private static SurfaceAnimationThread sInstance;
+ private static Handler sHandler;
+
+ private SurfaceAnimationThread() {
+ super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
+ }
+
+ private static void ensureThreadLocked() {
+ if (sInstance == null) {
+ sInstance = new SurfaceAnimationThread();
+ sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
+ sHandler = new Handler(sInstance.getLooper());
+ }
+ }
+
+ public static SurfaceAnimationThread get() {
+ synchronized (SurfaceAnimationThread.class) {
+ ensureThreadLocked();
+ return sInstance;
+ }
+ }
+
+ public static Handler getHandler() {
+ synchronized (SurfaceAnimationThread.class) {
+ ensureThreadLocked();
+ return sHandler;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
new file mode 100644
index 0000000..713d58b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+
+import java.io.PrintWriter;
+
+/**
+ * A class that can run animations on objects that have a set of child surfaces. We do this by
+ * reparenting all child surfaces of an object onto a new surface, called the "Leash". The Leash
+ * gets attached in the surface hierarchy where the the children were attached to. We then hand off
+ * the Leash to the component handling the animation, which is specified by the
+ * {@link AnimationAdapter}. When the animation is done animating, our callback to finish the
+ * animation will be invoked, at which we reparent the children back to the original parent.
+ */
+class SurfaceAnimator {
+
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "SurfaceAnimator" : TAG_WM;
+ private final WindowManagerService mService;
+ private AnimationAdapter mAnimation;
+ private SurfaceControl mLeash;
+ private final Animatable mAnimatable;
+ private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback;
+ private final Runnable mAnimationFinishedCallback;
+ private boolean mAnimationStartDelayed;
+
+ /**
+ * @param animatable The object to animate.
+ * @param animationFinishedCallback Callback to invoke when an animation has finished running.
+ */
+ SurfaceAnimator(Animatable animatable, Runnable animationFinishedCallback,
+ WindowManagerService service) {
+ mAnimatable = animatable;
+ mService = service;
+ mAnimationFinishedCallback = animationFinishedCallback;
+ mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback);
+ }
+
+ private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback) {
+ return anim -> {
+ synchronized (mService.mWindowMap) {
+ if (anim != mAnimation) {
+ // Callback was from another animation - ignore.
+ return;
+ }
+
+ final Transaction t = new Transaction();
+ SurfaceControl.openTransaction();
+ try {
+ reset(t);
+ animationFinishedCallback.run();
+ } finally {
+ // TODO: This should use pendingTransaction eventually, but right now things
+ // happening on the animation finished callback are happening on the global
+ // transaction.
+ SurfaceControl.mergeToGlobalTransaction(t);
+ SurfaceControl.closeTransaction();
+ }
+ }
+ };
+ }
+
+ /**
+ * Starts an animation.
+ *
+ * @param anim The object that bridges the controller, {@link SurfaceAnimator}, with the
+ * component responsible for running the animation. It runs the animation with
+ * {@link AnimationAdapter#startAnimation} once the hierarchy with
+ * the Leash has been set up.
+ * @param hidden Whether the container holding the child surfaces is currently visible or not.
+ * This is important as it will start with the leash hidden or visible before
+ * handing it to the component that is responsible to run the animation.
+ */
+ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
+ cancelAnimation(t, true /* restarting */);
+ mAnimation = anim;
+ final SurfaceControl surface = mAnimatable.getSurface();
+ if (surface == null) {
+ Slog.w(TAG, "Unable to start animation, surface is null or no children.");
+ cancelAnimation();
+ return;
+ }
+ mLeash = createAnimationLeash(surface, t,
+ mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), hidden);
+ mAnimatable.onLeashCreated(t, mLeash);
+ if (mAnimationStartDelayed) {
+ if (DEBUG_ANIM) Slog.i(TAG, "Animation start delayed");
+ return;
+ }
+ mAnimation.startAnimation(mLeash, t, mInnerAnimationFinishedCallback);
+ }
+
+ /**
+ * Begins with delaying all animations to start. Any subsequent call to {@link #startAnimation}
+ * will not start the animation until {@link #endDelayingAnimationStart} is called. When an
+ * animation start is being delayed, the animator is considered animating already.
+ */
+ void startDelayingAnimationStart() {
+
+ // We only allow delaying animation start we are not currently animating
+ if (!isAnimating()) {
+ mAnimationStartDelayed = true;
+ }
+ }
+
+ /**
+ * See {@link #startDelayingAnimationStart}.
+ */
+ void endDelayingAnimationStart() {
+ final boolean delayed = mAnimationStartDelayed;
+ mAnimationStartDelayed = false;
+ if (delayed && mAnimation != null) {
+ mAnimation.startAnimation(mLeash, mAnimatable.getPendingTransaction(),
+ mInnerAnimationFinishedCallback);
+ mAnimatable.commitPendingTransaction();
+ }
+ }
+
+ /**
+ * @return Whether we are currently running an animation, or we have a pending animation that
+ * is waiting to be started with {@link #endDelayingAnimationStart}
+ */
+ boolean isAnimating() {
+ return mAnimation != null;
+ }
+
+ /**
+ * @return The current animation spec if we are running an animation, or {@code null} otherwise.
+ */
+ AnimationAdapter getAnimation() {
+ return mAnimation;
+ }
+
+ /**
+ * Cancels any currently running animation.
+ */
+ void cancelAnimation() {
+ cancelAnimation(mAnimatable.getPendingTransaction(), false /* restarting */);
+ mAnimatable.commitPendingTransaction();
+ }
+
+ /**
+ * Sets the layer of the surface.
+ * <p>
+ * When the layer of the surface needs to be adjusted, we need to set it on the leash if the
+ * surface is reparented to the leash. This method takes care of that.
+ */
+ void setLayer(Transaction t, int layer) {
+ t.setLayer(mLeash != null ? mLeash : mAnimatable.getSurface(), layer);
+ }
+
+ /**
+ * Reparents the surface.
+ *
+ * @see #setLayer
+ */
+ void reparent(Transaction t, SurfaceControl newParent) {
+ t.reparent(mLeash != null ? mLeash : mAnimatable.getSurface(), newParent.getHandle());
+ }
+
+ /**
+ * @return True if the surface is attached to the leash; false otherwise.
+ */
+ boolean hasLeash() {
+ return mLeash != null;
+ }
+
+ private void cancelAnimation(Transaction t, boolean restarting) {
+ if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting);
+ final SurfaceControl leash = mLeash;
+ final AnimationAdapter animation = mAnimation;
+ reset(t);
+ if (animation != null) {
+ if (!mAnimationStartDelayed) {
+ animation.onAnimationCancelled(leash);
+ }
+ if (!restarting) {
+ mAnimationFinishedCallback.run();
+ }
+ }
+ if (!restarting) {
+ mAnimationStartDelayed = false;
+ }
+ }
+
+ private void reset(Transaction t) {
+ final SurfaceControl surface = mAnimatable.getSurface();
+ final SurfaceControl parent = mAnimatable.getParentSurface();
+
+ // If the surface was destroyed, we don't care to reparent it back.
+ final boolean destroy = mLeash != null && surface != null && parent != null;
+ if (destroy) {
+ if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent");
+ t.reparent(surface, parent.getHandle());
+ }
+ mLeash = null;
+ mAnimation = null;
+
+ // Make sure to inform the animatable after the leash was destroyed.
+ if (destroy) {
+ mAnimatable.onLeashDestroyed(t);
+ }
+ }
+
+ private SurfaceControl createAnimationLeash(SurfaceControl surface, Transaction t, int width,
+ int height, boolean hidden) {
+ if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
+ final SurfaceControl.Builder builder = mAnimatable.makeLeash()
+ .setName(surface + " - animation-leash")
+ .setSize(width, height);
+ final SurfaceControl leash = builder.build();
+ if (!hidden) {
+ t.show(leash);
+ }
+ t.reparent(surface, leash.getHandle());
+ return leash;
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mAnimation="); pw.print(mAnimation);
+ pw.print(" mLeash="); pw.println(mLeash);
+ }
+
+ /**
+ * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
+ * component that is running the animation when the animation is finished.
+ */
+ interface OnAnimationFinishedCallback {
+ void onAnimationFinished(AnimationAdapter anim);
+ }
+
+ /**
+ * Interface to be animated by {@link SurfaceAnimator}.
+ */
+ interface Animatable {
+
+ /**
+ * @return The pending transaction that will be committed in the next frame.
+ */
+ @NonNull Transaction getPendingTransaction();
+
+ /**
+ * Schedules a commit of the pending transaction.
+ */
+ void commitPendingTransaction();
+
+ /**
+ * Called when the was created.
+ *
+ * @param t The transaction to use to apply any necessary changes.
+ * @param leash The leash that was created.
+ */
+ void onLeashCreated(Transaction t, SurfaceControl leash);
+
+ /**
+ * Called when the leash is being destroyed, and the surface was reparented back to the
+ * original parent.
+ *
+ * @param t The transaction to use to apply any necessary changes.
+ */
+ void onLeashDestroyed(Transaction t);
+
+ /**
+ * @return A new child surface.
+ */
+ SurfaceControl.Builder makeLeash();
+
+ /**
+ * @return The surface of the object to be animated.
+ */
+ @Nullable SurfaceControl getSurface();
+
+ /**
+ * @return The parent of the surface object to be animated.
+ */
+ @Nullable SurfaceControl getParentSurface();
+
+ /**
+ * @return The width of the surface to be animated.
+ */
+ int getSurfaceWidth();
+
+ /**
+ * @return The height of the surface to be animated.
+ */
+ int getSurfaceHeight();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 87d0a40..ca9f3a9 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -16,15 +16,11 @@
package com.android.server.wm;
-import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.dipToPixel;
@@ -44,7 +40,6 @@
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.Display;
-import android.view.DisplayInfo;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
new file mode 100644
index 0000000..bb5706c
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.Nullable;
+import android.app.IActivityManager;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.Display;
+import android.view.IWindow;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputWindowHandle;
+
+/**
+ * Controller for task positioning by drag.
+ */
+class TaskPositioningController {
+ private final WindowManagerService mService;
+ private final InputManagerService mInputManager;
+ private final InputMonitor mInputMonitor;
+ private final IActivityManager mActivityManager;
+
+ @GuardedBy("WindowManagerSerivce.mWindowMap")
+ private @Nullable TaskPositioner mTaskPositioner;
+
+ boolean isPositioningLocked() {
+ return mTaskPositioner != null;
+ }
+
+ InputWindowHandle getDragWindowHandleLocked() {
+ return mTaskPositioner != null ? mTaskPositioner.mDragWindowHandle : null;
+ }
+
+ TaskPositioningController(WindowManagerService service, InputManagerService inputManager,
+ InputMonitor inputMonitor, IActivityManager activityManager) {
+ mService = service;
+ mInputMonitor = inputMonitor;
+ mInputManager = inputManager;
+ mActivityManager = activityManager;
+ }
+
+ boolean startMovingTask(IWindow window, float startX, float startY) {
+ WindowState win = null;
+ synchronized (mService.mWindowMap) {
+ win = mService.windowForClientLocked(null, window, false);
+ // win shouldn't be null here, pass it down to startPositioningLocked
+ // to get warning if it's null.
+ if (!startPositioningLocked(
+ win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
+ return false;
+ }
+ }
+ try {
+ mActivityManager.setFocusedTask(win.getTask().mTaskId);
+ } catch(RemoteException e) {}
+ return true;
+ }
+
+ void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
+ int taskId = -1;
+ synchronized (mService.mWindowMap) {
+ final Task task = displayContent.findTaskForResizePoint(x, y);
+ if (task != null) {
+ if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
+ task.preserveOrientationOnResize(), x, y)) {
+ return;
+ }
+ taskId = task.mTaskId;
+ } else {
+ taskId = displayContent.taskIdFromPoint(x, y);
+ }
+ }
+ if (taskId >= 0) {
+ try {
+ mActivityManager.setFocusedTask(taskId);
+ } catch(RemoteException e) {}
+ }
+ }
+
+ private boolean startPositioningLocked(WindowState win, boolean resize,
+ boolean preserveOrientation, float startX, float startY) {
+ if (DEBUG_TASK_POSITIONING)
+ Slog.d(TAG_WM, "startPositioningLocked: "
+ + "win=" + win + ", resize=" + resize + ", preserveOrientation="
+ + preserveOrientation + ", {" + startX + ", " + startY + "}");
+
+ if (win == null || win.getAppToken() == null) {
+ Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
+ return false;
+ }
+ if (win.mInputChannel == null) {
+ Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
+ + " probably being removed");
+ return false;
+ }
+
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent == null) {
+ Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
+ return false;
+ }
+
+ Display display = displayContent.getDisplay();
+ mTaskPositioner = new TaskPositioner(mService);
+ mTaskPositioner.register(displayContent);
+ mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+ // We need to grab the touch focus so that the touch events during the
+ // resizing/scrolling are not sent to the app. 'win' is the main window
+ // of the app, it may not have focus since there might be other windows
+ // on top (eg. a dialog window).
+ WindowState transferFocusFromWin = win;
+ if (mService.mCurrentFocus != null && mService.mCurrentFocus != win
+ && mService.mCurrentFocus.mAppToken == win.mAppToken) {
+ transferFocusFromWin = mService.mCurrentFocus;
+ }
+ if (!mInputManager.transferTouchFocus(
+ transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
+ Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
+ mTaskPositioner.unregister();
+ mTaskPositioner = null;
+ mInputMonitor.updateInputWindowsLw(true /*force*/);
+ return false;
+ }
+
+ mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
+ return true;
+ }
+
+ void finishPositioning() {
+ if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishPositioning");
+
+ synchronized (mService.mWindowMap) {
+ if (mTaskPositioner != null) {
+ mTaskPositioner.unregister();
+ mTaskPositioner = null;
+ mInputMonitor.updateInputWindowsLw(true /*force*/);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 832d395..28b1390 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1114,12 +1114,12 @@
return false;
}
- final Rect displayContentRect = mTmpRect;
+ final Rect displayStableRect = mTmpRect;
final Rect contentBounds = mTmpRect2;
// Calculate the content bounds excluding the area occupied by IME
- getDisplayContent().getContentRect(displayContentRect);
- contentBounds.set(displayContentRect);
+ getDisplayContent().getStableRect(displayStableRect);
+ contentBounds.set(displayStableRect);
int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
imeTop += imeWin.getGivenContentInsetsLw().top;
@@ -1127,7 +1127,7 @@
contentBounds.bottom = imeTop;
}
- final int yOffset = displayContentRect.bottom - contentBounds.bottom;
+ final int yOffset = displayStableRect.bottom - contentBounds.bottom;
final int dividerWidth =
getDisplayContent().mDividerControllerLocked.getContentWidth();
@@ -1139,7 +1139,7 @@
// occluded by IME. We shift its bottom up by the height of the IME, but
// leaves at least 30% of the top stack visible.
final int minTopStackBottom =
- getMinTopStackBottom(displayContentRect, getRawBounds().bottom);
+ getMinTopStackBottom(displayStableRect, getRawBounds().bottom);
final int bottom = Math.max(
getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
minTopStackBottom);
@@ -1159,7 +1159,7 @@
final int topBeforeImeAdjust =
getRawBounds().top - dividerWidth + dividerWidthInactive;
final int minTopStackBottom =
- getMinTopStackBottom(displayContentRect,
+ getMinTopStackBottom(displayStableRect,
getRawBounds().top - dividerWidth);
final int top = Math.max(
getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
new file mode 100644
index 0000000..56175c7
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Point;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+
+/**
+ * Animation spec for regular window animations.
+ */
+public class WindowAnimationSpec implements AnimationSpec {
+
+ private Animation mAnimation;
+ private final Point mPosition = new Point();
+ private final ThreadLocal<Tmp> mThreadLocalTmps = ThreadLocal.withInitial(Tmp::new);
+
+ public WindowAnimationSpec(Animation animation, Point position) {
+ mAnimation = animation;
+ mPosition.set(position.x, position.y);
+ }
+
+ @Override
+ public boolean getDetachWallpaper() {
+ return mAnimation.getDetachWallpaper();
+ }
+
+ @Override
+ public int getBackgroundColor() {
+ return mAnimation.getBackgroundColor();
+ }
+
+ @Override
+ public long getDuration() {
+ return mAnimation.computeDurationHint();
+ }
+
+ @Override
+ public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
+ final Tmp tmp = mThreadLocalTmps.get();
+ tmp.transformation.clear();
+ mAnimation.getTransformation(currentPlayTime, tmp.transformation);
+ tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
+ t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
+ t.setAlpha(leash, tmp.transformation.getAlpha());
+ }
+
+ private static class Tmp {
+ final Transformation transformation = new Transformation();
+ final float[] floats = new float[9];
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e598224..8c9948e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -755,7 +755,7 @@
// Whether or not a layout can cause a wake up when theater mode is enabled.
boolean mAllowTheaterModeWakeFromLayout;
- TaskPositioner mTaskPositioner;
+ final TaskPositioningController mTaskPositioningController;
final DragDropController mDragDropController;
// For frozen screen animations.
@@ -769,6 +769,7 @@
int mTransactionSequence;
final WindowAnimator mAnimator;
+ final SurfaceAnimationRunner mSurfaceAnimationRunner;
final BoundsAnimationController mBoundsAnimationController;
@@ -1082,10 +1083,13 @@
mHoldingScreenWakeLock.setReferenceCounted(false);
mAnimator = new WindowAnimator(this);
+ mSurfaceAnimationRunner = new SurfaceAnimationRunner();
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
+ mTaskPositioningController =
+ new TaskPositioningController(this, mInputManager, mInputMonitor, mActivityManager);
mDragDropController = new DragDropController(this, mH.getLooper());
LocalServices.addService(WindowManagerInternal.class, new LocalService());
@@ -4440,107 +4444,6 @@
}
}
- boolean startMovingTask(IWindow window, float startX, float startY) {
- WindowState win = null;
- synchronized (mWindowMap) {
- win = windowForClientLocked(null, window, false);
- // win shouldn't be null here, pass it down to startPositioningLocked
- // to get warning if it's null.
- if (!startPositioningLocked(
- win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
- return false;
- }
- }
- try {
- mActivityManager.setFocusedTask(win.getTask().mTaskId);
- } catch(RemoteException e) {}
- return true;
- }
-
- private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
- int taskId = -1;
- synchronized (mWindowMap) {
- final Task task = displayContent.findTaskForResizePoint(x, y);
- if (task != null) {
- if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
- task.preserveOrientationOnResize(), x, y)) {
- return;
- }
- taskId = task.mTaskId;
- } else {
- taskId = displayContent.taskIdFromPoint(x, y);
- }
- }
- if (taskId >= 0) {
- try {
- mActivityManager.setFocusedTask(taskId);
- } catch(RemoteException e) {}
- }
- }
-
- private boolean startPositioningLocked(WindowState win, boolean resize,
- boolean preserveOrientation, float startX, float startY) {
- if (DEBUG_TASK_POSITIONING)
- Slog.d(TAG_WM, "startPositioningLocked: "
- + "win=" + win + ", resize=" + resize + ", preserveOrientation="
- + preserveOrientation + ", {" + startX + ", " + startY + "}");
-
- if (win == null || win.getAppToken() == null) {
- Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
- return false;
- }
- if (win.mInputChannel == null) {
- Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
- + " probably being removed");
- return false;
- }
-
- final DisplayContent displayContent = win.getDisplayContent();
- if (displayContent == null) {
- Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
- return false;
- }
-
- Display display = displayContent.getDisplay();
- mTaskPositioner = new TaskPositioner(this);
- mTaskPositioner.register(displayContent);
- mInputMonitor.updateInputWindowsLw(true /*force*/);
-
- // We need to grab the touch focus so that the touch events during the
- // resizing/scrolling are not sent to the app. 'win' is the main window
- // of the app, it may not have focus since there might be other windows
- // on top (eg. a dialog window).
- WindowState transferFocusFromWin = win;
- if (mCurrentFocus != null && mCurrentFocus != win
- && mCurrentFocus.mAppToken == win.mAppToken) {
- transferFocusFromWin = mCurrentFocus;
- }
- if (!mInputManager.transferTouchFocus(
- transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
- Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
- mTaskPositioner.unregister();
- mTaskPositioner = null;
- mInputMonitor.updateInputWindowsLw(true /*force*/);
- return false;
- }
-
- mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
- return true;
- }
-
- private void finishPositioning() {
- if (DEBUG_TASK_POSITIONING) {
- Slog.d(TAG_WM, "finishPositioning");
- }
- synchronized (mWindowMap) {
- if (mTaskPositioner != null) {
- mTaskPositioner.unregister();
- mTaskPositioner = null;
- mInputMonitor.updateInputWindowsLw(true /*force*/);
- }
- }
- }
-
// -------------------------------------------------------------
// Input Events and Focus Management
// -------------------------------------------------------------
@@ -5003,12 +4906,13 @@
}
case TAP_OUTSIDE_TASK: {
- handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
+ mTaskPositioningController.handleTapOutsideTask(
+ (DisplayContent)msg.obj, msg.arg1, msg.arg2);
}
break;
case FINISH_TASK_POSITIONING: {
- finishPositioning();
+ mTaskPositioningController.finishPositioning();
}
break;
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
new file mode 100644
index 0000000..16c9c1b
--- /dev/null
+++ b/services/coverage/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.coverage",
+ srcs: ["java/**/*.java"],
+ libs: ["jacocoagent"],
+}
diff --git a/services/coverage/Android.mk b/services/coverage/Android.mk
deleted file mode 100644
index da99994..0000000
--- a/services/coverage/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.coverage
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := jacocoagent
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
new file mode 100644
index 0000000..0505204
--- /dev/null
+++ b/services/devicepolicy/Android.bp
@@ -0,0 +1,9 @@
+java_library_static {
+ name: "services.devicepolicy",
+ srcs: ["java/**/*.java"],
+
+ libs: [
+ "conscrypt",
+ "services.core",
+ ],
+}
diff --git a/services/devicepolicy/Android.mk b/services/devicepolicy/Android.mk
deleted file mode 100644
index 7020f17..0000000
--- a/services/devicepolicy/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.devicepolicy
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := conscrypt services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b979ff4..91ba87e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -79,7 +79,6 @@
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
-import android.app.admin.IDevicePolicyManager;
import android.app.admin.NetworkEvent;
import android.app.admin.PasswordMetrics;
import android.app.admin.SecurityLog;
@@ -740,7 +739,7 @@
private static final String TAG_ORGANIZATION_NAME = "organization-name";
private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
- private static final String TAG_IS_LOGOUT_BUTTON_ENABLED = "is_logout_button_enabled";
+ private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
final DeviceAdminInfo info;
@@ -790,7 +789,7 @@
boolean requireAutoTime = false; // Can only be set by a device owner.
boolean forceEphemeralUsers = false; // Can only be set by a device owner.
boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner.
- boolean isLogoutButtonEnabled = false; // Can only be set by a device owner.
+ boolean isLogoutEnabled = false; // Can only be set by a device owner.
// one notification after enabling + one more after reboots
static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
@@ -1108,10 +1107,10 @@
out.text(organizationName);
out.endTag(null, TAG_ORGANIZATION_NAME);
}
- if (isLogoutButtonEnabled) {
- out.startTag(null, TAG_IS_LOGOUT_BUTTON_ENABLED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutButtonEnabled));
- out.endTag(null, TAG_IS_LOGOUT_BUTTON_ENABLED);
+ if (isLogoutEnabled) {
+ out.startTag(null, TAG_IS_LOGOUT_ENABLED);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutEnabled));
+ out.endTag(null, TAG_IS_LOGOUT_ENABLED);
}
}
@@ -1286,8 +1285,8 @@
} else {
Log.w(LOG_TAG, "Missing text when loading organization name");
}
- } else if (TAG_IS_LOGOUT_BUTTON_ENABLED.equals(tag)) {
- isLogoutButtonEnabled = Boolean.parseBoolean(
+ } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
+ isLogoutEnabled = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
@@ -11581,35 +11580,35 @@
}
@Override
- public synchronized void setLogoutButtonEnabled(ComponentName admin, boolean enabled) {
+ public synchronized void setLogoutEnabled(ComponentName admin, boolean enabled) {
if (!mHasFeature) {
return;
}
Preconditions.checkNotNull(admin);
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- if (enabled == isLogoutButtonEnabledInternalLocked()) {
+ if (enabled == isLogoutEnabledInternalLocked()) {
// already in the requested state
return;
}
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
- deviceOwner.isLogoutButtonEnabled = enabled;
+ deviceOwner.isLogoutEnabled = enabled;
saveSettingsLocked(mInjector.userHandleGetCallingUserId());
}
@Override
- public boolean isLogoutButtonEnabled() {
+ public boolean isLogoutEnabled() {
if (!mHasFeature) {
return false;
}
synchronized (this) {
- return isLogoutButtonEnabledInternalLocked();
+ return isLogoutEnabledInternalLocked();
}
}
- private boolean isLogoutButtonEnabledInternalLocked() {
+ private boolean isLogoutEnabledInternalLocked() {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
- return (deviceOwner != null) && deviceOwner.isLogoutButtonEnabled;
+ return (deviceOwner != null) && deviceOwner.isLogoutEnabled;
}
}
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
new file mode 100644
index 0000000..3745e89
--- /dev/null
+++ b/services/midi/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.midi",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/midi/Android.mk b/services/midi/Android.mk
deleted file mode 100644
index faac01c..0000000
--- a/services/midi/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.midi
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/net/Android.bp b/services/net/Android.bp
new file mode 100644
index 0000000..e0ae68f
--- /dev/null
+++ b/services/net/Android.bp
@@ -0,0 +1,4 @@
+java_library_static {
+ name: "services.net",
+ srcs: ["java/**/*.java"],
+}
diff --git a/services/net/Android.mk b/services/net/Android.mk
deleted file mode 100644
index 408794e..0000000
--- a/services/net/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.net
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_AIDL_INCLUDES += \
- system/netd/server/binder
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index b305b33..fdb366c 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -163,10 +163,10 @@
// TODO: Find an lighter weight approach.
private class LoggingCallbackWrapper extends Callback {
private static final String PREFIX = "INVOKE ";
- private final Callback mCallback;
+ private Callback mCallback;
public LoggingCallbackWrapper(Callback callback) {
- mCallback = (callback != null) ? callback : new Callback();
+ mCallback = callback;
}
private void log(String msg) {
@@ -1283,7 +1283,6 @@
stopAllIP();
resetLinkProperties();
- mCallback.onLinkPropertiesChange(new LinkProperties(mLinkProperties));
if (mStartTimeMillis > 0) {
recordMetric(IpManagerEvent.COMPLETE_LIFECYCLE);
mStartTimeMillis = 0;
diff --git a/services/print/Android.bp b/services/print/Android.bp
new file mode 100644
index 0000000..80a8c75
--- /dev/null
+++ b/services/print/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.print",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/print/Android.mk b/services/print/Android.mk
deleted file mode 100644
index 00eb2e4..0000000
--- a/services/print/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.print
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
new file mode 100644
index 0000000..979e891
--- /dev/null
+++ b/services/restrictions/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.restrictions",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/restrictions/Android.mk b/services/restrictions/Android.mk
deleted file mode 100644
index 57d1c46..0000000
--- a/services/restrictions/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.restrictions
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/tests/Android.mk b/services/tests/Android.mk
deleted file mode 100644
index 40369ee..0000000
--- a/services/tests/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
index 7160d7f..a44f5c4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import android.content.Intent;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -61,14 +62,13 @@
mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory);
mStarter = spy(new ActivityStarter(mController, mService, mService.mStackSupervisor,
mock(ActivityStartInterceptor.class)));
- doReturn(mStarter).when(mFactory).obtainStarter();
+ doReturn(mStarter).when(mFactory).obtain();
}
/**
* Ensures that pending launches are processed.
*/
@Test
- @Presubmit
public void testPendingActivityLaunches() {
final Random random = new Random();
@@ -88,4 +88,20 @@
verify(mStarter, times(1)).startResolvedActivity(eq(activity), eq(source), eq(null),
eq(null), eq(startFlags), eq(resume), eq(null), eq(null), eq(null));
}
+
+
+ /**
+ * Ensures instances are recycled after execution.
+ */
+ @Test
+ public void testRecycling() throws Exception {
+ final Intent intent = new Intent();
+ final ActivityStarter optionStarter = new ActivityStarter(mController, mService,
+ mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
+ optionStarter
+ .setIntent(intent)
+ .setReason("Test")
+ .execute();
+ verify(mFactory, times(1)).recycle(eq(optionStarter));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index e8194dd..589a89b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -63,6 +63,7 @@
import static android.app.ActivityManager.START_INTENT_NOT_RESOLVED;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.ActivityStarter.Factory;
/**
* Tests for the {@link ActivityStarter} class.
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
index 0ea8d4f..5d739a3 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
@@ -32,6 +32,9 @@
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -57,7 +60,7 @@
private ConfigHelper mMockConfigHelper;
private PackageManagerHelper mMockPackageManagerHelper;
- private FakeClockHelper mFakeClock;
+ private FakeClock mFakeClock;
private FakeIntentHelper mFakeIntentHelper;
private PackageStatusStorage mPackageStatusStorage;
private PackageTracker mPackageTracker;
@@ -66,7 +69,7 @@
public void setUp() throws Exception {
Context context = InstrumentationRegistry.getContext();
- mFakeClock = new FakeClockHelper();
+ mFakeClock = new FakeClock();
// Read-only interfaces so are easy to mock.
mMockConfigHelper = mock(ConfigHelper.class);
@@ -1444,18 +1447,33 @@
}
}
- private static class FakeClockHelper implements ClockHelper {
+ private static class FakeClock extends Clock {
private long currentTime = 1000;
@Override
- public long currentTimestamp() {
+ public long millis() {
return currentTime;
}
public void incrementClock(long millis) {
currentTime += millis;
}
+
+ @Override
+ public ZoneId getZone() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Clock withZone(ZoneId zone) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Instant instant() {
+ throw new UnsupportedOperationException();
+ }
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 87b34ab..86ce90c 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -18,6 +18,7 @@
import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
+import static android.app.usage.UsageStatsManager.REASON_PREDICTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
@@ -364,4 +365,29 @@
reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
}
+
+ @Test
+ public void testPredictionTimedout() throws Exception {
+ AppStandbyController controller = setupController();
+ setChargingState(controller, false);
+ controller.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+ REASON_PREDICTED + "CTS", 1 * HOUR_MS);
+
+ // Fast forward 12 hours
+ mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
+ controller.checkIdleStates(USER_ID);
+ // Should still be in predicted bucket, since prediction timeout is 1 day since prediction
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller));
+ // Fast forward two more hours
+ mInjector.mElapsedRealtime += 2 * HOUR_MS;
+ controller.checkIdleStates(USER_ID);
+ // Should have now applied prediction timeout
+ assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
+
+ // Fast forward RARE bucket
+ mInjector.mElapsedRealtime += RARE_THRESHOLD;
+ controller.checkIdleStates(USER_ID);
+ // Should continue to apply prediction timeout
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
new file mode 100644
index 0000000..9ecf51e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+
+import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Choreographer;
+import android.view.Choreographer.FrameCallback;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+
+import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Test class for {@link SurfaceAnimationRunner}.
+ *
+ * runtest frameworks-services -c com.android.server.wm.SurfaceAnimationRunnerTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class SurfaceAnimationRunnerTest extends WindowTestsBase {
+
+ @Mock SurfaceControl mMockSurface;
+ @Mock Transaction mMockTransaction;
+ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ private SurfaceAnimationRunner mSurfaceAnimationRunner;
+ private CountDownLatch mFinishCallbackLatch;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ mFinishCallbackLatch = new CountDownLatch(1);
+ mSurfaceAnimationRunner = new SurfaceAnimationRunner(null /* callbackProvider */,
+ mMockTransaction);
+ }
+
+ private void finishedCallback() {
+ mFinishCallbackLatch.countDown();
+ }
+
+ @Test
+ public void testAnimation() throws Exception {
+ mSurfaceAnimationRunner
+ .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
+ this::finishedCallback);
+
+ // Ensure that the initial transformation has been applied.
+ final Matrix m = new Matrix();
+ m.setTranslate(-10, 0);
+ verify(mMockTransaction, atLeastOnce()).setMatrix(eq(mMockSurface), eq(m), any());
+ verify(mMockTransaction, atLeastOnce()).setAlpha(eq(mMockSurface), eq(1.0f));
+
+ mFinishCallbackLatch.await(1, SECONDS);
+ assertFinishCallbackCalled();
+
+ m.setTranslate(10, 0);
+ verify(mMockTransaction, atLeastOnce()).setMatrix(eq(mMockSurface), eq(m), any());
+
+ // At least 3 times: After initialization, first frame, last frame.
+ verify(mMockTransaction, atLeast(3)).setAlpha(eq(mMockSurface), eq(1.0f));
+ }
+
+ @Test
+ public void testCancel_notStarted() throws Exception {
+ mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), mMockTransaction);
+ mSurfaceAnimationRunner
+ .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
+ this::finishedCallback);
+ mSurfaceAnimationRunner.onAnimationCancelled(mMockSurface);
+ waitUntilHandlersIdle();
+ assertTrue(mSurfaceAnimationRunner.mPendingAnimations.isEmpty());
+ assertFinishCallbackNotCalled();
+ //verify(mMockSurface).release();
+ }
+
+ @Test
+ public void testCancel_running() throws Exception {
+ mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), mMockTransaction);
+ mSurfaceAnimationRunner
+ .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
+ this::finishedCallback);
+ waitUntilNextFrame();
+ assertFalse(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
+ mSurfaceAnimationRunner.onAnimationCancelled(mMockSurface);
+ assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
+ waitUntilHandlersIdle();
+ assertFinishCallbackNotCalled();
+ //verify(mMockSurface).release();
+ }
+
+ private void waitUntilNextFrame() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mSurfaceAnimationRunner.mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT,
+ latch::countDown, null /* token */);
+ latch.await();
+ }
+
+ private void assertFinishCallbackCalled() {
+ assertEquals(0, mFinishCallbackLatch.getCount());
+ }
+
+ private void assertFinishCallbackNotCalled() {
+ assertEquals(1, mFinishCallbackLatch.getCount());
+ }
+
+ private AnimationSpec createTranslateAnimation() {
+ final Animation a = new TranslateAnimation(-10, 10, 0, 0);
+ a.initialize(0, 0, 0, 0);
+ a.setDuration(50);
+ return new WindowAnimationSpec(a, new Point(0, 0));
+ }
+
+ /**
+ * Callback provider that doesn't animate at all.
+ */
+ private static final class NoOpFrameCallbackProvider implements AnimationFrameCallbackProvider {
+
+ @Override
+ public void postFrameCallback(FrameCallback callback) {
+ }
+
+ @Override
+ public void postCommitCallback(Runnable runnable) {
+ }
+
+ @Override
+ public long getFrameTime() {
+ return 0;
+ }
+
+ @Override
+ public long getFrameDelay() {
+ return 0;
+ }
+
+ @Override
+ public void setFrameDelay(long delay) {
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
new file mode 100644
index 0000000..9a52042
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Builder;
+import android.view.SurfaceControl.Transaction;
+import android.view.SurfaceSession;
+
+import com.google.android.collect.Lists;
+
+import com.android.server.wm.SurfaceAnimator.Animatable;
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+/**
+ * Test class for {@link SurfaceAnimatorTest}.
+ *
+ * runtest frameworks-services -c com.android.server.wm.SurfaceAnimatorTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class SurfaceAnimatorTest extends WindowTestsBase {
+
+ @Mock
+ AnimationAdapter mSpec;
+ @Mock
+ AnimationAdapter mSpec2;
+ @Mock Transaction mTransaction;
+
+ private SurfaceAnimator mSurfaceAnimator;
+ private SurfaceControl mParent;
+ private SurfaceControl mSurface;
+ private boolean mFinishedCallbackCalled;
+ private SurfaceControl mLeash;
+ private SurfaceSession mSession = new SurfaceSession();
+
+ private final Animatable mAnimatable = new Animatable() {
+ @Override
+ public Transaction getPendingTransaction() {
+ return mTransaction;
+ }
+
+ @Override
+ public void commitPendingTransaction() {
+ }
+
+ @Override
+ public void onLeashCreated(Transaction t, SurfaceControl leash) {
+ }
+
+ @Override
+ public void onLeashDestroyed(Transaction t) {
+ }
+
+ @Override
+ public Builder makeLeash() {
+ return new SurfaceControl.Builder(mSession) {
+
+ @Override
+ public SurfaceControl build() {
+ mLeash = super.build();
+ return mLeash;
+ }
+ }.setParent(mParent);
+ }
+
+ @Override
+ public SurfaceControl getSurface() {
+ return mSurface;
+ }
+
+ @Override
+ public SurfaceControl getParentSurface() {
+ return mParent;
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ return 1;
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return 1;
+ }
+ };
+
+ private final Runnable mFinishedCallback = () -> {
+ mFinishedCallbackCalled = true;
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ mParent = sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface parent")
+ .setSize(3000, 3000)
+ .build();
+ mSurface = sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1)
+ .build();
+ mFinishedCallbackCalled = false;
+ mLeash = null;
+ mSurfaceAnimator = new SurfaceAnimator(mAnimatable, mFinishedCallback, sWm);
+ }
+
+ @Test
+ public void testRunAnimation() throws Exception {
+ mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+ final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
+ OnAnimationFinishedCallback.class);
+
+ assertTrue(mSurfaceAnimator.isAnimating());
+ assertNotNull(mSurfaceAnimator.getAnimation());
+ verify(mTransaction).reparent(eq(mSurface), eq(mLeash.getHandle()));
+ verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
+
+ callbackCaptor.getValue().onAnimationFinished(mSpec);
+ assertFalse(mSurfaceAnimator.isAnimating());
+ assertNull(mSurfaceAnimator.getAnimation());
+ assertTrue(mFinishedCallbackCalled);
+
+ // TODO: Verify reparenting once we use mPendingTransaction to reparent it back
+ }
+
+ @Test
+ public void testOverrideAnimation() throws Exception {
+ mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+ mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */);
+
+ assertFalse(mFinishedCallbackCalled);
+
+ final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
+ OnAnimationFinishedCallback.class);
+ assertTrue(mSurfaceAnimator.isAnimating());
+ assertNotNull(mSurfaceAnimator.getAnimation());
+ verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
+
+ // First animation was finished, but this shouldn't cancel the second animation
+ callbackCaptor.getValue().onAnimationFinished(mSpec);
+ assertTrue(mSurfaceAnimator.isAnimating());
+
+ // Second animation was finished
+ verify(mSpec2).startAnimation(any(), any(), callbackCaptor.capture());
+ callbackCaptor.getValue().onAnimationFinished(mSpec2);
+ assertFalse(mSurfaceAnimator.isAnimating());
+ assertTrue(mFinishedCallbackCalled);
+ }
+
+ @Test
+ public void testCancelAnimation() throws Exception {
+ mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+ assertTrue(mSurfaceAnimator.isAnimating());
+ mSurfaceAnimator.cancelAnimation();
+ assertFalse(mSurfaceAnimator.isAnimating());
+ verify(mSpec).onAnimationCancelled(any());
+ assertTrue(mFinishedCallbackCalled);
+ }
+
+ @Test
+ public void testDelayingAnimationStart() throws Exception {
+ mSurfaceAnimator.startDelayingAnimationStart();
+ mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+ verifyZeroInteractions(mSpec);
+ assertTrue(mSurfaceAnimator.isAnimating());
+ mSurfaceAnimator.endDelayingAnimationStart();
+ verify(mSpec).startAnimation(any(), any(), any());
+ }
+
+ @Test
+ public void testDelayingAnimationStartAndCancelled() throws Exception {
+ mSurfaceAnimator.startDelayingAnimationStart();
+ mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+ mSurfaceAnimator.cancelAnimation();
+ verifyZeroInteractions(mSpec);
+ assertFalse(mSurfaceAnimator.isAnimating());
+ assertTrue(mFinishedCallbackCalled);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
new file mode 100644
index 0000000..89447a9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.InputChannel;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+/**
+ * Tests for the {@link TaskPositioningController} class.
+ *
+ * atest com.android.server.wm.TaskPositioningControllerTests
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public class TaskPositioningControllerTests extends WindowTestsBase {
+ private static final int TIMEOUT_MS = 1000;
+ private TaskPositioningController mTarget;
+ private WindowState mWindow;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(sWm.mTaskPositioningController);
+ mTarget = sWm.mTaskPositioningController;
+
+ when(sWm.mInputManager.transferTouchFocus(
+ any(InputChannel.class),
+ any(InputChannel.class))).thenReturn(true);
+
+ mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
+ mWindow.mInputChannel = new InputChannel();
+ synchronized (sWm.mWindowMap) {
+ sWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
+ }
+ }
+
+ @Test
+ public void testStartAndFinishPositioning() throws Exception {
+ synchronized (sWm.mWindowMap) {
+ assertFalse(mTarget.isPositioningLocked());
+ assertNull(mTarget.getDragWindowHandleLocked());
+ }
+
+ assertTrue(mTarget.startMovingTask(mWindow.mClient, 0, 0));
+
+ synchronized (sWm.mWindowMap) {
+ assertTrue(mTarget.isPositioningLocked());
+ assertNotNull(mTarget.getDragWindowHandleLocked());
+ }
+
+ assertTrue(sWm.mH.runWithScissors(() -> {
+ mTarget.finishPositioning();
+ }, TIMEOUT_MS));
+
+ assertFalse(mTarget.isPositioningLocked());
+ assertNull(mTarget.getDragWindowHandleLocked());
+ }
+
+ @Test
+ public void testHandleTapOutsideTask() throws Exception {
+ synchronized (sWm.mWindowMap) {
+
+ assertFalse(mTarget.isPositioningLocked());
+ assertNull(mTarget.getDragWindowHandleLocked());
+ }
+
+ final DisplayContent content = mock(DisplayContent.class);
+ when(content.findTaskForResizePoint(anyInt(), anyInt())).thenReturn(mWindow.getTask());
+ assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow());
+
+ mTarget.handleTapOutsideTask(content, 0, 0);
+
+ synchronized (sWm.mWindowMap) {
+ assertTrue(mTarget.isPositioningLocked());
+ assertNotNull(mTarget.getDragWindowHandleLocked());
+ }
+
+ assertTrue(sWm.mH.runWithScissors(() -> {
+ mTarget.finishPositioning();
+ }, TIMEOUT_MS));
+
+ assertFalse(mTarget.isPositioningLocked());
+ assertNull(mTarget.getDragWindowHandleLocked());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 4c5e291..c699a94 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -185,6 +185,7 @@
void waitUntilHandlersIdle() {
sWm.mH.runWithScissors(() -> { }, 0);
sWm.mAnimationHandler.runWithScissors(() -> { }, 0);
+ SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0);
}
private WindowToken createWindowToken(
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
new file mode 100644
index 0000000..1064b6e
--- /dev/null
+++ b/services/usage/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.usage",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/usage/Android.mk b/services/usage/Android.mk
deleted file mode 100644
index f1cbe98..0000000
--- a/services/usage/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.usage
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 5aef55b..6ac4b36 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -72,14 +72,13 @@
private static final String ATTR_SCREEN_IDLE = "screenIdleTime";
// Elapsed timebase time when app was last used
private static final String ATTR_ELAPSED_IDLE = "elapsedIdleTime";
+ // Elapsed timebase time when the app bucket was last predicted externally
+ private static final String ATTR_LAST_PREDICTED_TIME = "lastPredictedTime";
+ // The standby bucket for the app
private static final String ATTR_CURRENT_BUCKET = "appLimitBucket";
+ // The reason the app was put in the above bucket
private static final String ATTR_BUCKETING_REASON = "bucketReason";
- // State that was last informed to listeners, since boot
- private static final int STATE_UNINFORMED = 0;
- private static final int STATE_ACTIVE = 1;
- private static final int STATE_IDLE = 2;
-
// device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
private long mElapsedDuration; // Total device on duration since device was "born"
@@ -92,13 +91,21 @@
private boolean mScreenOn;
- private static class AppUsageHistory {
+ static class AppUsageHistory {
+ // Debug
final byte[] recent = new byte[HISTORY_SIZE];
+ // Last used time using elapsed timebase
long lastUsedElapsedTime;
+ // Last used time using screen_on timebase
long lastUsedScreenTime;
+ // Last predicted time using elapsed timebase
+ long lastPredictedTime;
+ // Standby bucket
@UsageStatsManager.StandbyBuckets
int currentBucket;
+ // Reason for setting the standby bucket. TODO: Switch to int.
String bucketingReason;
+ // In-memory only, last bucket for which the listeners were informed
int lastInformedBucket;
}
@@ -269,6 +276,7 @@
appUsageHistory = new AppUsageHistory();
appUsageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
+ appUsageHistory.lastPredictedTime = getElapsedTime(0);
appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_NEVER;
appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
appUsageHistory.lastInformedBucket = -1;
@@ -295,6 +303,14 @@
}
}
+ public AppUsageHistory getAppUsageHistory(String packageName, int userId,
+ long elapsedRealtime) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory appUsageHistory =
+ getPackageHistory(userHistory, packageName, elapsedRealtime, true);
+ return appUsageHistory;
+ }
+
public void setAppStandbyBucket(String packageName, int userId, long elapsedRealtime,
int bucket, String reason) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
@@ -302,6 +318,9 @@
getPackageHistory(userHistory, packageName, elapsedRealtime, true);
appUsageHistory.currentBucket = bucket;
appUsageHistory.bucketingReason = reason;
+ if (reason.startsWith(UsageStatsManager.REASON_PREDICTED)) {
+ appUsageHistory.lastPredictedTime = getElapsedTime(elapsedRealtime);
+ }
if (DEBUG) {
Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
+ ", reason=" + appUsageHistory.bucketingReason);
@@ -322,7 +341,7 @@
return appUsageHistory != null ? appUsageHistory.bucketingReason : null;
}
- private long getElapsedTime(long elapsedRealtime) {
+ public long getElapsedTime(long elapsedRealtime) {
return (elapsedRealtime - mElapsedSnapshot + mElapsedDuration);
}
@@ -431,6 +450,12 @@
Long.parseLong(parser.getAttributeValue(null, ATTR_ELAPSED_IDLE));
appUsageHistory.lastUsedScreenTime =
Long.parseLong(parser.getAttributeValue(null, ATTR_SCREEN_IDLE));
+ String lastPredictedTimeString = parser.getAttributeValue(null,
+ ATTR_LAST_PREDICTED_TIME);
+ if (lastPredictedTimeString != null) {
+ appUsageHistory.lastPredictedTime =
+ Long.parseLong(lastPredictedTimeString);
+ }
String currentBucketString = parser.getAttributeValue(null,
ATTR_CURRENT_BUCKET);
appUsageHistory.currentBucket = currentBucketString == null
@@ -441,6 +466,7 @@
if (appUsageHistory.bucketingReason == null) {
appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
}
+ appUsageHistory.lastInformedBucket = -1;
userHistory.put(packageName, appUsageHistory);
}
}
@@ -477,6 +503,8 @@
Long.toString(history.lastUsedElapsedTime));
xml.attribute(null, ATTR_SCREEN_IDLE,
Long.toString(history.lastUsedScreenTime));
+ xml.attribute(null, ATTR_LAST_PREDICTED_TIME,
+ Long.toString(history.lastPredictedTime));
xml.attribute(null, ATTR_CURRENT_BUCKET,
Integer.toString(history.currentBucket));
xml.attribute(null, ATTR_BUCKETING_REASON, history.bucketingReason);
@@ -512,6 +540,8 @@
TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw);
idpw.print(" lastUsedScreenOn=");
TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
+ idpw.print(" lastPredictedTime=");
+ TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastPredictedTime, idpw);
idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
idpw.print(" bucket=" + appUsageHistory.currentBucket
+ " reason=" + appUsageHistory.bucketingReason);
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 3d20a64..d8086bb 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -18,6 +18,7 @@
import static android.app.usage.UsageStatsManager.REASON_DEFAULT;
import static android.app.usage.UsageStatsManager.REASON_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_USAGE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
@@ -118,6 +119,9 @@
STANDBY_BUCKET_RARE
};
+ // Expiration time for predicted bucket
+ private static final long PREDICTION_TIMEOUT = 12 * ONE_HOUR;
+
// To name the lock for stack traces
static class Lock {}
@@ -388,25 +392,27 @@
STANDBY_BUCKET_EXEMPTED);
} else {
synchronized (mAppIdleLock) {
- String bucketingReason = mAppIdleHistory.getAppStandbyReason(packageName,
+ AppIdleHistory.AppUsageHistory app =
+ mAppIdleHistory.getAppUsageHistory(packageName,
userId, elapsedRealtime);
// If the bucket was forced by the developer, leave it alone
- if (REASON_FORCED.equals(bucketingReason)) {
+ if (REASON_FORCED.equals(app.bucketingReason)) {
continue;
}
+ boolean predictionLate = false;
// If the bucket was moved up due to usage, let the timeouts apply.
- if (REASON_DEFAULT.equals(bucketingReason)
- || REASON_USAGE.equals(bucketingReason)
- || REASON_TIMEOUT.equals(bucketingReason)) {
- int oldBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId,
- elapsedRealtime);
+ if (REASON_DEFAULT.equals(app.bucketingReason)
+ || REASON_USAGE.equals(app.bucketingReason)
+ || REASON_TIMEOUT.equals(app.bucketingReason)
+ || (predictionLate = predictionTimedOut(app, elapsedRealtime))) {
+ int oldBucket = app.currentBucket;
int newBucket = getBucketForLocked(packageName, userId,
elapsedRealtime);
if (DEBUG) {
Slog.d(TAG, " Old bucket=" + oldBucket
+ ", newBucket=" + newBucket);
}
- if (oldBucket < newBucket) {
+ if (oldBucket < newBucket || predictionLate) {
mAppIdleHistory.setAppStandbyBucket(packageName, userId,
elapsedRealtime, newBucket, REASON_TIMEOUT);
maybeInformListeners(packageName, userId, elapsedRealtime,
@@ -424,6 +430,14 @@
return true;
}
+ private boolean predictionTimedOut(AppIdleHistory.AppUsageHistory app, long elapsedRealtime) {
+ return app.bucketingReason != null
+ && app.bucketingReason.startsWith(REASON_PREDICTED)
+ && app.lastPredictedTime > 0
+ && mAppIdleHistory.getElapsedTime(elapsedRealtime)
+ - app.lastPredictedTime > PREDICTION_TIMEOUT;
+ }
+
private void maybeInformListeners(String packageName, int userId,
long elapsedRealtime, int bucket) {
synchronized (mAppIdleLock) {
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
new file mode 100644
index 0000000..0cd9ac3
--- /dev/null
+++ b/services/usb/Android.bp
@@ -0,0 +1,14 @@
+java_library_static {
+ name: "services.usb",
+ srcs: ["java/**/*.java"],
+
+ libs: [
+ "services.core",
+ "android.hidl.manager-V1.0-java",
+ ],
+
+ static_libs: [
+ "android.hardware.usb-V1.0-java",
+ "android.hardware.usb-V1.1-java",
+ ],
+}
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
deleted file mode 100644
index 55bfccf..0000000
--- a/services/usb/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.usb
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core \
-android.hidl.manager-V1.0-java
-
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java \
-android.hardware.usb-V1.1-java
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
new file mode 100644
index 0000000..390406f
--- /dev/null
+++ b/services/voiceinteraction/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+ name: "services.voiceinteraction",
+ srcs: ["java/**/*.java"],
+ libs: ["services.core"],
+}
diff --git a/services/voiceinteraction/Android.mk b/services/voiceinteraction/Android.mk
deleted file mode 100644
index c9e5dd0..0000000
--- a/services/voiceinteraction/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.voiceinteraction
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index a5d67c6..dd2a6df 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -83,7 +83,10 @@
public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
/** @hide */
- @StringDef({FORMAT_3GPP, FORMAT_3GPP2})
+ @StringDef(prefix = { "FORMAT_" }, value = {
+ FORMAT_3GPP,
+ FORMAT_3GPP2
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface Format {}
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 8cdad3f..da51c86 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -116,7 +116,6 @@
*/
public int getSuggestedRetryTime() { return mSuggestedRetryTime; }
-
/**
* @return The unique id of the data connection.
*/
@@ -183,16 +182,57 @@
.append(" active=").append(mActive)
.append(" type=").append(mType)
.append(" ifname=").append(mIfname)
- .append(" mtu=").append(mMtu)
.append(" addresses=").append(mAddresses)
.append(" dnses=").append(mDnses)
.append(" gateways=").append(mGateways)
.append(" pcscf=").append(mPcscfs)
+ .append(" mtu=").append(mMtu)
.append("}");
return sb.toString();
}
@Override
+ public boolean equals (Object o) {
+ if (this == o) return true;
+
+ if (o == null || !(o instanceof DataCallResponse)) {
+ return false;
+ }
+
+ DataCallResponse other = (DataCallResponse) o;
+ return this.mStatus == other.mStatus
+ && this.mSuggestedRetryTime == other.mSuggestedRetryTime
+ && this.mCid == other.mCid
+ && this.mActive == other.mActive
+ && this.mType.equals(other.mType)
+ && this.mIfname.equals(other.mIfname)
+ && mAddresses.size() == other.mAddresses.size()
+ && mAddresses.containsAll(other.mAddresses)
+ && mDnses.size() == other.mDnses.size()
+ && mDnses.containsAll(other.mDnses)
+ && mGateways.size() == other.mGateways.size()
+ && mGateways.containsAll(other.mGateways)
+ && mPcscfs.size() == other.mPcscfs.size()
+ && mPcscfs.containsAll(other.mPcscfs)
+ && mMtu == other.mMtu;
+ }
+
+ @Override
+ public int hashCode() {
+ return mStatus * 31
+ + mSuggestedRetryTime * 37
+ + mCid * 41
+ + mActive * 43
+ + mType.hashCode() * 47
+ + mIfname.hashCode() * 53
+ + mAddresses.hashCode() * 59
+ + mDnses.hashCode() * 61
+ + mGateways.hashCode() * 67
+ + mPcscfs.hashCode() * 71
+ + mMtu * 73;
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.java b/telephony/java/android/telephony/data/InterfaceAddress.java
index 947d0ff..00d212a 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.java
+++ b/telephony/java/android/telephony/data/InterfaceAddress.java
@@ -78,6 +78,23 @@
*/
public int getNetworkPrefixLength() { return mPrefixLength; }
+ @Override
+ public boolean equals (Object o) {
+ if (this == o) return true;
+
+ if (o == null || !(o instanceof InterfaceAddress)) {
+ return false;
+ }
+
+ InterfaceAddress other = (InterfaceAddress) o;
+ return this.mInetAddress.equals(other.mInetAddress)
+ && this.mPrefixLength == other.mPrefixLength;
+ }
+
+ @Override
+ public int hashCode() {
+ return mInetAddress.hashCode() * 31 + mPrefixLength * 37;
+ }
@Override
public int describeContents() {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 5a4db99..1670e6b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -16,15 +16,23 @@
package android.telephony.ims.stub;
+import android.content.Context;
+import android.content.Intent;
import android.os.RemoteException;
+import android.util.Log;
import com.android.ims.ImsConfig;
import com.android.ims.ImsConfigListener;
import com.android.ims.internal.IImsConfig;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
/**
- * Base implementation of ImsConfig, which implements stub versions of the methods
- * in the IImsConfig AIDL. Override the methods that your implementation of ImsConfig supports.
+ * Base implementation of ImsConfig.
+ * Override the methods that your implementation of ImsConfig supports.
*
* DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
* will break other implementations of ImsConfig maintained by other ImsServices.
@@ -34,10 +42,25 @@
* 1) Items provisioned by the operator.
* 2) Items configured by user. Mainly service feature class.
*
+ * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
+ * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
+ * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in
+ * during initialization, or times when a lot of configuration parameters are being set/get
+ * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed
+ * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be
+ * performed every time.
* @hide
*/
-public class ImsConfigImplBase extends IImsConfig.Stub {
+public class ImsConfigImplBase {
+
+ static final private String TAG = "ImsConfigImplBase";
+
+ ImsConfigStub mImsConfigStub;
+
+ public ImsConfigImplBase(Context context) {
+ mImsConfigStub = new ImsConfigStub(this, context);
+ }
/**
* Gets the value for ims service/capabilities parameters from the provisioned
@@ -46,7 +69,6 @@
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @return value in Integer format.
*/
- @Override
public int getProvisionedValue(int item) throws RemoteException {
return -1;
}
@@ -58,7 +80,6 @@
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @return value in String format.
*/
- @Override
public String getProvisionedStringValue(int item) throws RemoteException {
return null;
}
@@ -72,7 +93,6 @@
* @param value in Integer format.
* @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
*/
- @Override
public int setProvisionedValue(int item, int value) throws RemoteException {
return ImsConfig.OperationStatusConstants.FAILED;
}
@@ -86,7 +106,6 @@
* @param value in String format.
* @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
*/
- @Override
public int setProvisionedStringValue(int item, String value) throws RemoteException {
return ImsConfig.OperationStatusConstants.FAILED;
}
@@ -100,7 +119,6 @@
* @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
* @param listener feature value returned asynchronously through listener.
*/
- @Override
public void getFeatureValue(int feature, int network, ImsConfigListener listener)
throws RemoteException {
}
@@ -115,7 +133,6 @@
* @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
* @param listener, provided if caller needs to be notified for set result.
*/
- @Override
public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
throws RemoteException {
}
@@ -124,7 +141,6 @@
* Gets the value for IMS VoLTE provisioned.
* This should be the same as the operator provisioned value if applies.
*/
- @Override
public boolean getVolteProvisioned() throws RemoteException {
return false;
}
@@ -134,7 +150,6 @@
*
* @param listener Video quality value returned asynchronously through listener.
*/
- @Override
public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
}
@@ -144,7 +159,233 @@
* @param quality, defines the value of video quality.
* @param listener, provided if caller needs to be notified for set result.
*/
- @Override
public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
}
+
+ public IImsConfig getIImsConfig() { return mImsConfigStub; }
+
+ /**
+ * Updates provisioning value and notifies the framework of the change.
+ * Doesn't call #setProvisionedValue and assumes the result succeeded.
+ * This should only be used by modem when they implicitly changed provisioned values.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in Integer format.
+ */
+ public final void notifyProvisionedValueChanged(int item, int value) {
+ mImsConfigStub.updateCachedValue(item, value, true);
+ }
+
+ /**
+ * Updates provisioning value and notifies the framework of the change.
+ * Doesn't call #setProvisionedValue and assumes the result succeeded.
+ * This should only be used by modem when they implicitly changed provisioned values.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in String format.
+ */
+ public final void notifyProvisionedValueChanged(int item, String value) {
+ mImsConfigStub.updateCachedValue(item, value, true);
+ }
+
+ /**
+ * Implements the IImsConfig AIDL interface, which is called by potentially many processes
+ * in order to get/set configuration parameters.
+ *
+ * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl
+ * with actual implementations from vendors. This class caches provisioned values from
+ * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in,
+ * it first checks cache layer. If missed, it will call the vendor implementation of
+ * ImsConfigImplBase API.
+ * and cache the return value if the set succeeds.
+ *
+ * Provides APIs to get/set the IMS service feature/capability/parameters.
+ * The config items include:
+ * 1) Items provisioned by the operator.
+ * 2) Items configured by user. Mainly service feature class.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ static public class ImsConfigStub extends IImsConfig.Stub {
+ Context mContext;
+ WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
+ private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
+ private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+
+ @VisibleForTesting
+ public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context) {
+ mContext = context;
+ mImsConfigImplBaseWeakReference =
+ new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
+ }
+
+ /**
+ * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+ * if missed, it will call ImsConfigImplBase.getProvisionedValue.
+ * Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @return value in Integer format.
+ */
+ @Override
+ public synchronized int getProvisionedValue(int item) throws RemoteException {
+ if (mProvisionedIntValue.containsKey(item)) {
+ return mProvisionedIntValue.get(item);
+ } else {
+ int retVal = getImsConfigImpl().getProvisionedValue(item);
+ if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+ updateCachedValue(item, retVal, false);
+ }
+ return retVal;
+ }
+ }
+
+ /**
+ * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+ * if missed, it will call #ImsConfigImplBase.getProvisionedValue.
+ * Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @return value in String format.
+ */
+ @Override
+ public synchronized String getProvisionedStringValue(int item) throws RemoteException {
+ if (mProvisionedIntValue.containsKey(item)) {
+ return mProvisionedStringValue.get(item);
+ } else {
+ String retVal = getImsConfigImpl().getProvisionedStringValue(item);
+ if (retVal != null) {
+ updateCachedValue(item, retVal, false);
+ }
+ return retVal;
+ }
+ }
+
+ /**
+ * Sets the value for IMS service/capabilities parameters by the operator device
+ * management entity. It sets the config item value in the provisioned storage
+ * from which the master value is derived, and write it into local cache.
+ * Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in Integer format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ */
+ @Override
+ public synchronized int setProvisionedValue(int item, int value) throws RemoteException {
+ mProvisionedIntValue.remove(item);
+ int retVal = getImsConfigImpl().setProvisionedValue(item, value);
+ if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+ updateCachedValue(item, retVal, true);
+ } else {
+ Log.d(TAG, "Set provision value of " + item +
+ " to " + value + " failed with error code " + retVal);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Sets the value for IMS service/capabilities parameters by the operator device
+ * management entity. It sets the config item value in the provisioned storage
+ * from which the master value is derived, and write it into local cache.
+ * Synchronous blocking call.
+ *
+ * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in String format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ */
+ @Override
+ public synchronized int setProvisionedStringValue(int item, String value)
+ throws RemoteException {
+ mProvisionedStringValue.remove(item);
+ int retVal = getImsConfigImpl().setProvisionedStringValue(item, value);
+ if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+ updateCachedValue(item, retVal, true);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.getFeatureValue.
+ */
+ @Override
+ public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+ throws RemoteException {
+ getImsConfigImpl().getFeatureValue(feature, network, listener);
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.setFeatureValue.
+ */
+ @Override
+ public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+ throws RemoteException {
+ getImsConfigImpl().setFeatureValue(feature, network, value, listener);
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.getVolteProvisioned.
+ */
+ @Override
+ public boolean getVolteProvisioned() throws RemoteException {
+ return getImsConfigImpl().getVolteProvisioned();
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.getVideoQuality.
+ */
+ @Override
+ public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+ getImsConfigImpl().getVideoQuality(listener);
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.setVideoQuality.
+ */
+ @Override
+ public void setVideoQuality(int quality, ImsConfigListener listener)
+ throws RemoteException {
+ getImsConfigImpl().setVideoQuality(quality, listener);
+ }
+
+ private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
+ ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
+ if (ref == null) {
+ throw new RemoteException("Fail to get ImsConfigImpl");
+ } else {
+ return ref;
+ }
+ }
+
+ private void sendImsConfigChangedIntent(int item, int value) {
+ sendImsConfigChangedIntent(item, Integer.toString(value));
+ }
+
+ private void sendImsConfigChangedIntent(int item, String value) {
+ Intent configChangedIntent = new Intent(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
+ configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
+ configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
+ if (mContext != null) {
+ mContext.sendBroadcast(configChangedIntent);
+ }
+ }
+
+ protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) {
+ mProvisionedIntValue.put(item, value);
+ if (notifyChange) {
+ sendImsConfigChangedIntent(item, value);
+ }
+ }
+
+ protected synchronized void updateCachedValue(
+ int item, String value, boolean notifyChange) {
+ mProvisionedStringValue.put(item, value);
+ if (notifyChange) {
+ sendImsConfigChangedIntent(item, value);
+ }
+ }
+ }
}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index cf4c47b..cd0c4b1 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -619,6 +619,7 @@
Rlog.d(TAG, "setProvisionedValue(): item = " + item +
" value = " + value + " ret = " + ret);
}
+
return ret;
}
@@ -647,6 +648,7 @@
Rlog.d(TAG, "setProvisionedStringValue(): item = " + item +
", value =" + value);
}
+
return ret;
}
diff --git a/test-base/Android.bp b/test-base/Android.bp
new file mode 100644
index 0000000..a3fd345
--- /dev/null
+++ b/test-base/Android.bp
@@ -0,0 +1,88 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Build the android.test.base library
+// ===================================
+// This contains the junit.framework and android.test classes that were in
+// Android API level 25 excluding those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library {
+ name: "android.test.base",
+
+ srcs: ["src/**/*.java"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ ],
+
+}
+
+// Build the legacy-test library
+// =============================
+// This contains the junit.framework and android.test classes that were in
+// Android API level 25 excluding those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library {
+ name: "legacy-test",
+ static_libs: ["android.test.base"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ ],
+}
+
+// Build the repackaged.android.test.base library
+// ==============================================
+// This contains repackaged versions of the classes from legacy-test.
+java_library_static {
+ name: "repackaged.android.test.base",
+
+ static_libs: ["android.test.base"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ ],
+
+ jarjar_rules: "jarjar-rules.txt",
+}
+
+// Build the legacy-android-test library
+// =====================================
+// This contains the android.test classes that were in Android API level 25,
+// including those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library_static {
+ name: "legacy-android-test",
+
+ srcs: [
+ "src/android/**/*.java",
+ "src/com/**/*.java",
+ ],
+
+ static_libs: [
+ "android.test.runner",
+ "android.test.mock",
+ ],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ "junit",
+ ],
+}
diff --git a/test-base/Android.mk b/test-base/Android.mk
index 03bdcf23..5e5d040 100644
--- a/test-base/Android.mk
+++ b/test-base/Android.mk
@@ -16,50 +16,6 @@
LOCAL_PATH:= $(call my-dir)
-# Build the android.test.base library
-# ===================================
-# This contains the junit.framework and android.test classes that were in
-# Android API level 25 excluding those from android.test.runner.
-# Also contains the com.android.internal.util.Predicate[s] classes.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := android.test.base
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Build the legacy-test library
-# =============================
-# This contains the junit.framework and android.test classes that were in
-# Android API level 25 excluding those from android.test.runner.
-# Also contains the com.android.internal.util.Predicate[s] classes.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := legacy-test
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Build the repackaged.android.test.base library
-# ==============================================
-# This contains repackaged versions of the classes from legacy-test.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := repackaged.android.test.base
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
@@ -156,24 +112,6 @@
endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
-# Build the legacy-android-test library
-# =====================================
-# This contains the android.test classes that were in Android API level 25,
-# including those from android.test.runner.
-# Also contains the com.android.internal.util.Predicate[s] classes.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src/android) \
- $(call all-java-files-under, ../test-runner/src/android) \
- $(call all-java-files-under, ../test-mock/src/android) \
- $(call all-java-files-under, src/com)
-LOCAL_MODULE := legacy-android-test
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework junit
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
# Build the legacy.test.stubs library
# ===================================
include $(CLEAR_VARS)
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
new file mode 100644
index 0000000..8eddec4
--- /dev/null
+++ b/test-mock/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2008 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.
+//
+
+// Build the android.test.mock library
+// ===================================
+java_library {
+ name: "android.test.mock",
+
+ srcs: ["src/**/*.java"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ "legacy-test",
+ ],
+}
+
+// Build the repackaged.android.test.mock library
+// ==============================================
+java_library_static {
+ name: "repackaged.android.test.mock",
+
+ static_libs: ["android.test.mock"],
+
+ jarjar_rules: "jarjar-rules.txt",
+}
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
index 2c07955..a761a07 100644
--- a/test-mock/Android.mk
+++ b/test-mock/Android.mk
@@ -18,32 +18,6 @@
android_test_mock_source_files := $(call all-java-files-under, src/android/test/mock)
-# Build the repackaged.android.test.mock library
-# ==============================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../test-base/jarjar-rules.txt
-
-LOCAL_MODULE:= repackaged.android.test.mock
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Build the android.test.mock library
-# ===================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-LOCAL_MODULE:= android.test.mock
-
-include $(BUILD_JAVA_LIBRARY)
-
# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt
new file mode 120000
index 0000000..f6f7913
--- /dev/null
+++ b/test-mock/jarjar-rules.txt
@@ -0,0 +1 @@
+../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
new file mode 100644
index 0000000..104ae82
--- /dev/null
+++ b/test-runner/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2008 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.
+//
+
+// Build the android.test.runner library
+// =====================================
+java_library {
+ name: "android.test.runner",
+
+ srcs: ["src/**/*.java"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ "legacy-test",
+ "android.test.mock",
+ ],
+}
+
+// Build the repackaged.android.test.runner library
+// ================================================
+java_library_static {
+ name: "repackaged.android.test.runner",
+
+ static_libs: ["android.test.runner"],
+
+ jarjar_rules: "jarjar-rules.txt",
+}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 87fe831..67f1354 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -16,42 +16,6 @@
LOCAL_PATH:= $(call my-dir)
-# Build the android.test.runner library
-# =====================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := \
- core-oj \
- core-libart \
- framework \
- android.test.base \
- android.test.mock \
-
-LOCAL_MODULE:= android.test.runner
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Build the repackaged.android.test.runner library
-# ================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := \
- core-oj \
- core-libart \
- framework \
- android.test.base \
- android.test.mock \
-
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../test-base/jarjar-rules.txt
-
-LOCAL_MODULE:= repackaged.android.test.runner
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
diff --git a/test-runner/jarjar-rules.txt b/test-runner/jarjar-rules.txt
new file mode 120000
index 0000000..f6f7913
--- /dev/null
+++ b/test-runner/jarjar-rules.txt
@@ -0,0 +1 @@
+../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk
index 59bc729..5765575 100644
--- a/tests/BrowserPowerTest/Android.mk
+++ b/tests/BrowserPowerTest/Android.mk
@@ -18,8 +18,8 @@
# We only want this apk build for tests.
LOCAL_MODULE_TAGS := tests
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/CantSaveState1/Android.mk b/tests/CantSaveState1/Android.mk
deleted file mode 100644
index 6e9db6e..0000000
--- a/tests/CantSaveState1/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CantSaveState1
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CantSaveState1/AndroidManifest.xml b/tests/CantSaveState1/AndroidManifest.xml
deleted file mode 100644
index fadcaeb..0000000
--- a/tests/CantSaveState1/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.cantsavestate1">
- <application android:label="Can't Save 1" android:cantSaveState="true">
- <activity android:name="CantSave1Activity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/tests/CantSaveState1/res/layout/cant_save_1_activity.xml b/tests/CantSaveState1/res/layout/cant_save_1_activity.xml
deleted file mode 100644
index c5bf657..0000000
--- a/tests/CantSaveState1/res/layout/cant_save_1_activity.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
->
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="25dp"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="This app #1 can't save its state"
- />
-
-</LinearLayout>
diff --git a/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java b/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java
deleted file mode 100644
index 8879ed0..0000000
--- a/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.cantsavestate1;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class CantSave1Activity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.cant_save_1_activity);
- }
-}
diff --git a/tests/CantSaveState2/Android.mk b/tests/CantSaveState2/Android.mk
deleted file mode 100644
index add9214..0000000
--- a/tests/CantSaveState2/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CantSaveState2
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CantSaveState2/AndroidManifest.xml b/tests/CantSaveState2/AndroidManifest.xml
deleted file mode 100644
index 8f4f01d..0000000
--- a/tests/CantSaveState2/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.cantsavestate2">
- <application android:label="Can't Save 2" android:cantSaveState="true">
- <activity android:name="CantSave2Activity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/tests/CantSaveState2/res/layout/cant_save_2_activity.xml b/tests/CantSaveState2/res/layout/cant_save_2_activity.xml
deleted file mode 100644
index c5b8e3d..0000000
--- a/tests/CantSaveState2/res/layout/cant_save_2_activity.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
->
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="25dp"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="This app #2 can't save its state"
- />
-
-</LinearLayout>
diff --git a/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java b/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java
deleted file mode 100644
index 3ce63c7..0000000
--- a/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.cantsavestate2;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class CantSave2Activity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.cant_save_2_activity);
- }
-}
diff --git a/tests/CanvasCompare/Android.mk b/tests/CanvasCompare/Android.mk
index 90de503..b071ec4 100644
--- a/tests/CanvasCompare/Android.mk
+++ b/tests/CanvasCompare/Android.mk
@@ -23,7 +23,7 @@
LOCAL_MODULE_TAGS := tests
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
include $(BUILD_PACKAGE)
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
index c9f1161..56d7918 100644
--- a/tests/CoreTests/android/Android.mk
+++ b/tests/CoreTests/android/Android.mk
@@ -6,8 +6,14 @@
LOCAL_SRC_FILES := \
$(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle conscrypt org.apache.http.legacy
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := \
+ android.test.runner \
+ bouncycastle \
+ conscrypt \
+ org.apache.http.legacy \
+ android.test.base \
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := CoreTests
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
index 4e15729..85f7edf 100644
--- a/tests/DataIdleTest/Android.mk
+++ b/tests/DataIdleTest/Android.mk
@@ -20,8 +20,8 @@
LOCAL_MODULE_TAGS := tests
LOCAL_PACKAGE_NAME := DataIdleTest
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# We need to sign it to get access to the network usage history.
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
index d2ec753..1873cc1 100644
--- a/tests/FrameworkPerf/Android.mk
+++ b/tests/FrameworkPerf/Android.mk
@@ -7,8 +7,8 @@
LOCAL_PACKAGE_NAME := FrameworkPerf
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
index f8c8656..8550d70 100644
--- a/tests/HierarchyViewerTest/Android.mk
+++ b/tests/HierarchyViewerTest/Android.mk
@@ -7,7 +7,7 @@
LOCAL_PACKAGE_NAME := HierarchyViewerTest
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
include $(BUILD_PACKAGE)
diff --git a/tests/ImfTest/tests/Android.mk b/tests/ImfTest/tests/Android.mk
index 6042471..a0df959 100644
--- a/tests/ImfTest/tests/Android.mk
+++ b/tests/ImfTest/tests/Android.mk
@@ -7,8 +7,8 @@
# Include all test java files.
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := ImfTestTests
diff --git a/tests/Internal/Android.mk b/tests/Internal/Android.mk
index fc001e9..73181ec 100644
--- a/tests/Internal/Android.mk
+++ b/tests/Internal/Android.mk
@@ -11,7 +11,6 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := junit \
- legacy-android-test \
android-support-test \
mockito-target-minus-junit4
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
index 578e628..e186e9f 100644
--- a/tests/MemoryUsage/Android.mk
+++ b/tests/MemoryUsage/Android.mk
@@ -9,8 +9,8 @@
LOCAL_PACKAGE_NAME := MemoryUsage
LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
include $(BUILD_PACKAGE)
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
index dd9ff11..6fb6025 100644
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ b/tests/NetworkSecurityConfigTest/Android.mk
@@ -5,8 +5,13 @@
LOCAL_MODULE_TAGS := tests
LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle conscrypt
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := \
+ android.test.runner \
+ bouncycastle \
+ conscrypt \
+ android.test.base \
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index 359484e..030d5f4 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -27,8 +27,8 @@
LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
endif
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target legacy-android-test
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_PACKAGE_NAME := SoundTriggerTests
diff --git a/tests/SurfaceComposition/Android.mk b/tests/SurfaceComposition/Android.mk
index d97c3f4..1962791 100644
--- a/tests/SurfaceComposition/Android.mk
+++ b/tests/SurfaceComposition/Android.mk
@@ -27,7 +27,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
+
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
LOCAL_PACKAGE_NAME := SurfaceComposition
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
index 3c3cd77..2fa1950 100644
--- a/tests/TtsTests/Android.mk
+++ b/tests/TtsTests/Android.mk
@@ -20,8 +20,8 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target legacy-android-test
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_PACKAGE_NAME := TtsTests
diff --git a/tests/WindowAnimationJank/Android.mk b/tests/WindowAnimationJank/Android.mk
index f356afb..8aac8a1 100644
--- a/tests/WindowAnimationJank/Android.mk
+++ b/tests/WindowAnimationJank/Android.mk
@@ -27,7 +27,6 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
ub-uiautomator \
ub-janktesthelper \
- legacy-android-test \
junit
LOCAL_SDK_VERSION := current
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java
index ebf121a..22d88fb 100644
--- a/tests/net/java/android/net/ip/IpManagerTest.java
+++ b/tests/net/java/android/net/ip/IpManagerTest.java
@@ -69,8 +69,6 @@
/**
* Tests for IpManager.
- *
- * TODO: Rename to IpClientTest.
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -113,10 +111,6 @@
verify(mNMService, times(1)).registerObserver(arg.capture());
mObserver = arg.getValue();
reset(mNMService);
- final LinkProperties emptyLp = new LinkProperties();
- emptyLp.setInterfaceName(ifname);
- verify(mCb, timeout(100)).onLinkPropertiesChange(eq(emptyLp));
- reset(mCb);
return ipm;
}
diff --git a/tests/permission/Android.mk b/tests/permission/Android.mk
index 54688c8..7f81d9a 100644
--- a/tests/permission/Android.mk
+++ b/tests/permission/Android.mk
@@ -7,8 +7,8 @@
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_PACKAGE_NAME := FrameworkPermissionTests
include $(BUILD_PACKAGE)
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
index 16fe535..6e20d797 100644
--- a/tests/testables/tests/Android.mk
+++ b/tests/testables/tests/Android.mk
@@ -28,10 +28,9 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
mockito-target-minus-junit4 \
- legacy-android-test \
testables
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
LOCAL_CERTIFICATE := platform
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 33b5a8b..20a9f41 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -57,31 +57,30 @@
std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection(
const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) {
+ std::unique_ptr<ResourceTable> table;
+
io::IFile* table_file = collection->FindFile(kProtoResourceTablePath);
- if (table_file == nullptr) {
- diag->Error(DiagMessage(source) << "failed to find " << kProtoResourceTablePath);
- return {};
- }
+ if (table_file != nullptr) {
+ pb::ResourceTable pb_table;
+ std::unique_ptr<io::InputStream> in = table_file->OpenInputStream();
+ if (in == nullptr) {
+ diag->Error(DiagMessage(source) << "failed to open " << kProtoResourceTablePath);
+ return {};
+ }
- std::unique_ptr<io::InputStream> in = table_file->OpenInputStream();
- if (in == nullptr) {
- diag->Error(DiagMessage(source) << "failed to open " << kProtoResourceTablePath);
- return {};
- }
+ io::ZeroCopyInputAdaptor adaptor(in.get());
+ if (!pb_table.ParseFromZeroCopyStream(&adaptor)) {
+ diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath);
+ return {};
+ }
- pb::ResourceTable pb_table;
- io::ZeroCopyInputAdaptor adaptor(in.get());
- if (!pb_table.ParseFromZeroCopyStream(&adaptor)) {
- diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath);
- return {};
- }
-
- std::string error;
- std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
- if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
- diag->Error(DiagMessage(source)
- << "failed to deserialize " << kProtoResourceTablePath << ": " << error);
- return {};
+ std::string error;
+ table = util::make_unique<ResourceTable>();
+ if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
+ diag->Error(DiagMessage(source)
+ << "failed to deserialize " << kProtoResourceTablePath << ": " << error);
+ return {};
+ }
}
io::IFile* manifest_file = collection->FindFile(kAndroidManifestPath);
@@ -103,6 +102,7 @@
return {};
}
+ std::string error;
std::unique_ptr<xml::XmlResource> manifest = DeserializeXmlResourceFromPb(pb_node, &error);
if (manifest == nullptr) {
diag->Error(DiagMessage(source)
@@ -115,24 +115,21 @@
std::unique_ptr<LoadedApk> LoadedApk::LoadBinaryApkFromFileCollection(
const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) {
+ std::unique_ptr<ResourceTable> table;
+
io::IFile* table_file = collection->FindFile(kApkResourceTablePath);
- if (table_file == nullptr) {
- diag->Error(DiagMessage(source) << "failed to find " << kApkResourceTablePath);
-
- return {};
- }
-
- std::unique_ptr<io::IData> data = table_file->OpenAsData();
- if (data == nullptr) {
- diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
- return {};
- }
-
- std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
- BinaryResourceParser parser(diag, table.get(), source, data->data(), data->size(),
- collection.get());
- if (!parser.Parse()) {
- return {};
+ if (table_file != nullptr) {
+ table = util::make_unique<ResourceTable>();
+ std::unique_ptr<io::IData> data = table_file->OpenAsData();
+ if (data == nullptr) {
+ diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
+ return {};
+ }
+ BinaryResourceParser parser(diag, table.get(), source, data->data(), data->size(),
+ collection.get());
+ if (!parser.Parse()) {
+ return {};
+ }
}
io::IFile* manifest_file = collection->FindFile(kAndroidManifestPath);
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 2bd2405..964dacf 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -64,37 +64,39 @@
return false;
}
- // Resource table
- if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize the resource table");
- return false;
+ if (apk->GetResourceTable() != nullptr) {
+ // Resource table
+ if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "failed to serialize the resource table");
+ return false;
+ }
+
+ // Resources
+ for (const auto& package : apk->GetResourceTable()->packages) {
+ for (const auto& type : package->types) {
+ for (const auto& entry : type->entries) {
+ for (const auto& config_value : entry->values) {
+ const FileReference* file = ValueCast<FileReference>(config_value->value.get());
+ if (file != nullptr) {
+ if (file->file == nullptr) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "no file associated with " << *file);
+ return false;
+ }
+
+ if (!serializer->SerializeFile(file, writer)) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "failed to serialize file " << *file->path);
+ return false;
+ }
+ } // file
+ } // config_value
+ } // entry
+ } // type
+ } // package
}
- // Resources
- for (const auto& package : apk->GetResourceTable()->packages) {
- for (const auto& type : package->types) {
- for (const auto& entry : type->entries) {
- for (const auto& config_value : entry->values) {
- const FileReference* file = ValueCast<FileReference>(config_value->value.get());
- if (file != nullptr) {
- if (file->file == nullptr) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "no file associated with " << *file);
- return false;
- }
-
- if (!serializer->SerializeFile(file, writer)) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize file " << *file->path);
- return false;
- }
- } // file
- } // config_value
- } // entry
- } // type
- } // package
-
// Other files
std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
while (iterator->HasNext()) {
diff --git a/tools/locked_region_code_injection/Android.bp b/tools/locked_region_code_injection/Android.bp
index 6dd6059..5f81a2e 100644
--- a/tools/locked_region_code_injection/Android.bp
+++ b/tools/locked_region_code_injection/Android.bp
@@ -1,4 +1,4 @@
-java_library_host {
+java_binary_host {
name: "lockedregioncodeinjection",
manifest: "manifest.txt",
srcs: ["src/**/*.java"],
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index 735e872..b4c690f 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -41,7 +41,7 @@
*
* @hide RTT_API
*/
-@SystemService(Context.WIFI_RTT2_SERVICE)
+@SystemService(Context.WIFI_RTT_RANGING_SERVICE)
public class WifiRttManager {
private static final String TAG = "WifiRttManager";
private static final boolean VDBG = false;
diff --git a/wifi/java/android/net/wifi/rtt/package.html b/wifi/java/android/net/wifi/rtt/package.html
index 221b94b7..a0d407a 100644
--- a/wifi/java/android/net/wifi/rtt/package.html
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -5,7 +5,7 @@
<p>The primary entry point to Wi-Fi RTT capabilities is the
{@link android.net.wifi.rtt.WifiRttManager} class, which is acquired by calling
{@link android.content.Context#getSystemService(String)
- Context.getSystemService(Context.WIFI_RTT_SERVICE)}</p>
+ Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE)}</p>
<p>Some APIs may require the following user permissions:</p>
<ul>