Merge "Add Log.wtf when transitionTo is used improperly"
diff --git a/api/system-current.txt b/api/system-current.txt
index c81f4e9..6db91c6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40610,6 +40610,7 @@
method public boolean isSmsCapable();
method public boolean isTtyModeSupported();
method public boolean isVideoCallingEnabled();
+ method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
@@ -40623,6 +40624,7 @@
method public boolean setPreferredNetworkTypeToGlobal();
method public boolean setRadio(boolean);
method public boolean setRadioPower(boolean);
+ method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public void silenceRinger();
method public boolean supplyPin(java.lang.String);
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 54c3d1a..beb550c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -77,12 +77,23 @@
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound";
static const int ANIM_ENTRY_NAME_MAX = 256;
+static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed";
+static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason";
+// bootreasons list in "system/core/bootstat/bootstat.cpp".
+static const std::vector<std::string> PLAY_SOUND_BOOTREASON_BLACKLIST {
+ "kernel_panic",
+ "Panic",
+ "Watchdog",
+};
// ---------------------------------------------------------------------------
BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
mTimeCheckThread(NULL) {
mSession = new SurfaceComposerClient();
+
+ // If the system has already booted, the animation is not being used for a boot.
+ mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
}
BootAnimation::~BootAnimation() {}
@@ -776,13 +787,9 @@
break;
// only play audio file the first time we animate the part
- if (r == 0 && part.audioData) {
- // Read the system property to see if we should play the sound.
- // If not present, default to playing it.
- if (property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
- ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
- audioplay::playClip(part.audioData, part.audioLength);
- }
+ if (r == 0 && part.audioData && playSoundsAllowed()) {
+ ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
+ audioplay::playClip(part.audioData, part.audioLength);
}
glClearColor(
@@ -918,6 +925,30 @@
return animation;
}
+bool BootAnimation::playSoundsAllowed() const {
+ // Only play sounds for system boots, not runtime restarts.
+ if (!mSystemBoot) {
+ return false;
+ }
+
+ // Read the system property to see if we should play the sound.
+ // If it's not present, default to allowed.
+ if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
+ return false;
+ }
+
+ // Don't play sounds if this is a reboot due to an error.
+ char bootreason[PROPERTY_VALUE_MAX];
+ if (property_get(BOOTREASON_PROP_NAME, bootreason, nullptr) > 0) {
+ for (const auto& str : PLAY_SOUND_BOOTREASON_BLACKLIST) {
+ if (strcasecmp(str.c_str(), bootreason) == 0) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
bool BootAnimation::updateIsTimeAccurate() {
static constexpr long long MAX_TIME_IN_PAST = 60000LL * 60LL * 24LL * 30LL; // 30 days
static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL; // 90 minutes
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index a53216e..fd497a3 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -120,6 +120,7 @@
void releaseAnimation(Animation*) const;
bool parseAnimationDesc(Animation&);
bool preloadZip(Animation &animation);
+ bool playSoundsAllowed() const;
void checkExit();
@@ -137,6 +138,7 @@
sp<Surface> mFlingerSurface;
bool mClockEnabled;
bool mTimeIsAccurate;
+ bool mSystemBoot;
String8 mZipFileName;
SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread;
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
index 94214ff..633dd97 100644
--- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
@@ -52,7 +52,7 @@
IWifiManager wifiMgr
= IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
try {
- wifiMgr.setWifiEnabled(flag);
+ wifiMgr.setWifiEnabled("com.android.shell", flag);
}
catch (RemoteException e) {
System.err.println("Wi-Fi operation failed: " + e);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index ae78e218..c4eaccc 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -628,8 +628,8 @@
if (connection == null) {
return false;
}
- List<MotionEvent> events = MotionEventGenerator.getMotionEventsFromGestureDescription(
- gesture, 100);
+ List<GestureDescription.GestureStep> steps =
+ MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 100);
try {
synchronized (mLock) {
mGestureStatusCallbackSequence++;
@@ -641,8 +641,8 @@
callback, handler);
mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo);
}
- connection.sendMotionEvents(mGestureStatusCallbackSequence,
- new ParceledListSlice<>(events));
+ connection.sendGesture(mGestureStatusCallbackSequence,
+ new ParceledListSlice<>(steps));
}
} catch (RemoteException re) {
throw new RuntimeException(re);
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index fc9581e..d9b03fa 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -21,6 +21,8 @@
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
@@ -303,13 +305,37 @@
}
}
- private static class TouchPoint {
+ /**
+ * The location of a finger for gesture dispatch
+ *
+ * @hide
+ */
+ public static class TouchPoint implements Parcelable {
+ private static final int FLAG_IS_START_OF_PATH = 0x01;
+ private static final int FLAG_IS_END_OF_PATH = 0x02;
+
int mPathIndex;
boolean mIsStartOfPath;
boolean mIsEndOfPath;
float mX;
float mY;
+ public TouchPoint() {
+ }
+
+ public TouchPoint(TouchPoint pointToCopy) {
+ copyFrom(pointToCopy);
+ }
+
+ public TouchPoint(Parcel parcel) {
+ mPathIndex = parcel.readInt();
+ int startEnd = parcel.readInt();
+ mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0;
+ mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0;
+ mX = parcel.readFloat();
+ mY = parcel.readFloat();
+ }
+
void copyFrom(TouchPoint other) {
mPathIndex = other.mPathIndex;
mIsStartOfPath = other.mIsStartOfPath;
@@ -317,12 +343,94 @@
mX = other.mX;
mY = other.mY;
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mPathIndex);
+ int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0;
+ startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0;
+ dest.writeInt(startEnd);
+ dest.writeFloat(mX);
+ dest.writeFloat(mY);
+ }
+
+ public static final Parcelable.Creator<TouchPoint> CREATOR
+ = new Parcelable.Creator<TouchPoint>() {
+ public TouchPoint createFromParcel(Parcel in) {
+ return new TouchPoint(in);
+ }
+
+ public TouchPoint[] newArray(int size) {
+ return new TouchPoint[size];
+ }
+ };
+ }
+
+ /**
+ * A step along a gesture. Contains all of the touch points at a particular time
+ *
+ * @hide
+ */
+ public static class GestureStep implements Parcelable {
+ public long timeSinceGestureStart;
+ public int numTouchPoints;
+ public TouchPoint[] touchPoints;
+
+ public GestureStep(long timeSinceGestureStart, int numTouchPoints,
+ TouchPoint[] touchPointsToCopy) {
+ this.timeSinceGestureStart = timeSinceGestureStart;
+ this.numTouchPoints = numTouchPoints;
+ this.touchPoints = new TouchPoint[numTouchPoints];
+ for (int i = 0; i < numTouchPoints; i++) {
+ this.touchPoints[i] = new TouchPoint(touchPointsToCopy[i]);
+ }
+ }
+
+ public GestureStep(Parcel parcel) {
+ timeSinceGestureStart = parcel.readLong();
+ Parcelable[] parcelables =
+ parcel.readParcelableArray(TouchPoint.class.getClassLoader());
+ numTouchPoints = (parcelables == null) ? 0 : parcelables.length;
+ touchPoints = new TouchPoint[numTouchPoints];
+ for (int i = 0; i < numTouchPoints; i++) {
+ touchPoints[i] = (TouchPoint) parcelables[i];
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(timeSinceGestureStart);
+ dest.writeParcelableArray(touchPoints, flags);
+ }
+
+ public static final Parcelable.Creator<GestureStep> CREATOR
+ = new Parcelable.Creator<GestureStep>() {
+ public GestureStep createFromParcel(Parcel in) {
+ return new GestureStep(in);
+ }
+
+ public GestureStep[] newArray(int size) {
+ return new GestureStep[size];
+ }
+ };
}
/**
* Class to convert a GestureDescription to a series of MotionEvents.
+ *
+ * @hide
*/
- static class MotionEventGenerator {
+ public static class MotionEventGenerator {
/**
* Constants used to initialize all MotionEvents
*/
@@ -341,39 +449,53 @@
private static PointerCoords[] sPointerCoords;
private static PointerProperties[] sPointerProps;
- static List<MotionEvent> getMotionEventsFromGestureDescription(
+ static List<GestureStep> getGestureStepsFromGestureDescription(
GestureDescription description, int sampleTimeMs) {
- final List<MotionEvent> motionEvents = new ArrayList<>();
+ final List<GestureStep> gestureSteps = new ArrayList<>();
// Point data at each time we generate an event for
final TouchPoint[] currentTouchPoints =
getCurrentTouchPoints(description.getStrokeCount());
- // Point data sent in last touch event
- int lastTouchPointSize = 0;
- final TouchPoint[] lastTouchPoints =
- getLastTouchPoints(description.getStrokeCount());
-
+ int currentTouchPointSize = 0;
/* Loop through each time slice where there are touch points */
long timeSinceGestureStart = 0;
long nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart);
while (nextKeyPointTime >= 0) {
- timeSinceGestureStart = (lastTouchPointSize == 0) ? nextKeyPointTime
+ timeSinceGestureStart = (currentTouchPointSize == 0) ? nextKeyPointTime
: Math.min(nextKeyPointTime, timeSinceGestureStart + sampleTimeMs);
- int currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
+ currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
currentTouchPoints);
-
- appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
- currentTouchPoints, currentTouchPointSize, timeSinceGestureStart);
- lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
- lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
- timeSinceGestureStart);
- lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
- lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
- timeSinceGestureStart);
+ gestureSteps.add(new GestureStep(timeSinceGestureStart, currentTouchPointSize,
+ currentTouchPoints));
/* Move to next time slice */
nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1);
}
+ return gestureSteps;
+ }
+
+ public static List<MotionEvent> getMotionEventsFromGestureSteps(List<GestureStep> steps) {
+ final List<MotionEvent> motionEvents = new ArrayList<>();
+
+ // Number of points in last touch event
+ int lastTouchPointSize = 0;
+ TouchPoint[] lastTouchPoints;
+
+ for (int i = 0; i < steps.size(); i++) {
+ GestureStep step = steps.get(i);
+ int currentTouchPointSize = step.numTouchPoints;
+ lastTouchPoints = getLastTouchPoints(
+ Math.max(lastTouchPointSize, currentTouchPointSize));
+
+ appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
+ step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart);
+ lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
+ lastTouchPointSize, step.touchPoints, currentTouchPointSize,
+ step.timeSinceGestureStart);
+ lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
+ lastTouchPointSize, step.touchPoints, currentTouchPointSize,
+ step.timeSinceGestureStart);
+ }
return motionEvents;
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 7a55079..81cddba 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -88,5 +88,5 @@
void setSoftKeyboardCallbackEnabled(boolean enabled);
- void sendMotionEvents(int sequence, in ParceledListSlice events);
+ void sendGesture(int sequence, in ParceledListSlice gestureSteps);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a4c667f..5f8350f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -66,6 +66,7 @@
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -5591,7 +5592,11 @@
return;
}
- mSearchManager = new SearchManager(this, null);
+ try {
+ mSearchManager = new SearchManager(this, null);
+ } catch (ServiceNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
}
@Override
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index d6529d6..1367280 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1485,7 +1485,7 @@
*
* <p>If your app's <code>targetSdkVersion</code> is {@link android.os.Build.VERSION_CODES#M}
* or lower, child fragments being restored from the savedInstanceState are restored after
- * <code>onCreate</code> returns. When targeting @link android.os.Build.VERSION_CODES#N} or
+ * <code>onCreate</code> returns. When targeting {@link android.os.Build.VERSION_CODES#N} or
* above and running on an N or newer platform version
* they are restored by <code>Fragment.onCreate</code>.</p>
*
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index db7d54b..ec22ff6 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -128,7 +128,7 @@
/*
* Backup: is the current system wallpaper image eligible for off-device backup?
*/
- boolean isWallpaperBackupEligible(int userId);
+ boolean isWallpaperBackupEligible(int which, int userId);
/*
* Keyguard: register a callback for being notified that lock-state relevant
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 505e081..da99e80 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -27,6 +27,7 @@
import android.os.IBinder;
import android.os.IUserManager;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.IWindowManager;
@@ -192,12 +193,12 @@
}
- KeyguardManager() {
+ KeyguardManager() throws ServiceNotFoundException {
mWM = WindowManagerGlobal.getWindowManagerService();
mTrustManager = ITrustManager.Stub.asInterface(
- ServiceManager.getService(Context.TRUST_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE));
mUserManager = IUserManager.Stub.asInterface(
- ServiceManager.getService(Context.USER_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.USER_SERVICE));
}
/**
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index ac4abf5..ee6a3ac 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -31,6 +31,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
@@ -536,7 +537,7 @@
/**
* Reference to the shared system search service.
*/
- private static ISearchManager mService;
+ private final ISearchManager mService;
private final Context mContext;
@@ -547,11 +548,11 @@
private SearchDialog mSearchDialog;
- /*package*/ SearchManager(Context context, Handler handler) {
+ /*package*/ SearchManager(Context context, Handler handler) throws ServiceNotFoundException {
mContext = context;
mHandler = handler;
mService = ISearchManager.Stub.asInterface(
- ServiceManager.getService(Context.SEARCH_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.SEARCH_SERVICE));
}
/**
@@ -620,7 +621,7 @@
return;
}
- UiModeManager uiModeManager = new UiModeManager();
+ final UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
// Don't show search dialog on televisions.
if (uiModeManager.getCurrentModeType() != Configuration.UI_MODE_TYPE_TELEVISION) {
ensureSearchDialog();
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 55744b9..1778ca7 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -16,14 +16,10 @@
package android.app;
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.ISoundTriggerService;
-import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.os.IDropBoxManagerService;
-
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.IDevicePolicyManager;
import android.app.job.IJobScheduler;
import android.app.job.JobScheduler;
import android.app.trust.TrustManager;
@@ -36,7 +32,6 @@
import android.content.Context;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
-import android.content.pm.ILauncherApps;
import android.content.pm.IShortcutService;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutManager;
@@ -48,13 +43,15 @@
import android.hardware.SystemSensorManager;
import android.hardware.camera2.CameraManager;
import android.hardware.display.DisplayManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.IFingerprintService;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlService;
import android.hardware.input.InputManager;
import android.hardware.location.ContextHubManager;
+import android.hardware.radio.RadioManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbManager;
-import android.hardware.radio.RadioManager;
import android.location.CountryDetector;
import android.location.ICountryDetector;
import android.location.ILocationManager;
@@ -90,8 +87,10 @@
import android.net.wifi.p2p.WifiP2pManager;
import android.nfc.NfcManager;
import android.os.BatteryManager;
+import android.os.BatteryStats;
import android.os.DropBoxManager;
import android.os.HardwarePropertiesManager;
+import android.os.IBatteryPropertiesRegistrar;
import android.os.IBinder;
import android.os.IHardwarePropertiesManager;
import android.os.IPowerManager;
@@ -101,6 +100,7 @@
import android.os.Process;
import android.os.RecoverySystem;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemVibrator;
import android.os.UserHandle;
import android.os.UserManager;
@@ -109,8 +109,6 @@
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.IFingerprintService;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
import android.telecom.TelecomManager;
@@ -120,7 +118,6 @@
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
-import com.android.internal.policy.PhoneLayoutInflater;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityManager;
@@ -128,6 +125,13 @@
import android.view.inputmethod.InputMethodManager;
import android.view.textservice.TextServicesManager;
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.app.ISoundTriggerService;
+import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.os.IDropBoxManagerService;
+import com.android.internal.policy.PhoneLayoutInflater;
+
import java.util.HashMap;
/**
@@ -135,7 +139,7 @@
* Used by {@link ContextImpl}.
*/
final class SystemServiceRegistry {
- private final static String TAG = "SystemServiceRegistry";
+ private static final String TAG = "SystemServiceRegistry";
// Service registry information.
// This information is never changed once static initialization has completed.
@@ -166,8 +170,8 @@
registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
new CachedServiceFetcher<AccountManager>() {
@Override
- public AccountManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE);
+ public AccountManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.ACCOUNT_SERVICE);
IAccountManager service = IAccountManager.Stub.asInterface(b);
return new AccountManager(ctx, service);
}});
@@ -182,8 +186,8 @@
registerService(Context.ALARM_SERVICE, AlarmManager.class,
new CachedServiceFetcher<AlarmManager>() {
@Override
- public AlarmManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
+ public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
return new AlarmManager(service, ctx);
}});
@@ -212,15 +216,15 @@
registerService(Context.HDMI_CONTROL_SERVICE, HdmiControlManager.class,
new StaticServiceFetcher<HdmiControlManager>() {
@Override
- public HdmiControlManager createService() {
- IBinder b = ServiceManager.getService(Context.HDMI_CONTROL_SERVICE);
+ public HdmiControlManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.HDMI_CONTROL_SERVICE);
return new HdmiControlManager(IHdmiControlService.Stub.asInterface(b));
}});
registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,
new CachedServiceFetcher<ClipboardManager>() {
@Override
- public ClipboardManager createService(ContextImpl ctx) {
+ public ClipboardManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new ClipboardManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler());
}});
@@ -233,8 +237,8 @@
registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
@Override
- public ConnectivityManager createService(Context context) {
- IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+ public ConnectivityManager createService(Context context) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
return new ConnectivityManager(context, service);
}});
@@ -242,16 +246,17 @@
registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
new StaticServiceFetcher<CountryDetector>() {
@Override
- public CountryDetector createService() {
- IBinder b = ServiceManager.getService(Context.COUNTRY_DETECTOR);
+ public CountryDetector createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.COUNTRY_DETECTOR);
return new CountryDetector(ICountryDetector.Stub.asInterface(b));
}});
registerService(Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class,
new CachedServiceFetcher<DevicePolicyManager>() {
@Override
- public DevicePolicyManager createService(ContextImpl ctx) {
- return DevicePolicyManager.create(ctx);
+ public DevicePolicyManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.DEVICE_POLICY_SERVICE);
+ return new DevicePolicyManager(ctx, IDevicePolicyManager.Stub.asInterface(b));
}});
registerService(Context.DOWNLOAD_SERVICE, DownloadManager.class,
@@ -264,8 +269,12 @@
registerService(Context.BATTERY_SERVICE, BatteryManager.class,
new StaticServiceFetcher<BatteryManager>() {
@Override
- public BatteryManager createService() {
- return new BatteryManager();
+ public BatteryManager createService() throws ServiceNotFoundException {
+ IBatteryStats stats = IBatteryStats.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME));
+ IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub
+ .asInterface(ServiceManager.getServiceOrThrow("batteryproperties"));
+ return new BatteryManager(stats, registrar);
}});
registerService(Context.NFC_SERVICE, NfcManager.class,
@@ -278,16 +287,9 @@
registerService(Context.DROPBOX_SERVICE, DropBoxManager.class,
new CachedServiceFetcher<DropBoxManager>() {
@Override
- public DropBoxManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.DROPBOX_SERVICE);
+ public DropBoxManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.DROPBOX_SERVICE);
IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
- if (service == null) {
- // Don't return a DropBoxManager that will NPE upon use.
- // This also avoids caching a broken DropBoxManager in
- // getDropBoxManager during early boot, before the
- // DROPBOX_SERVICE is registered.
- return null;
- }
return new DropBoxManager(ctx, service);
}});
@@ -322,7 +324,7 @@
registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class,
new StaticServiceFetcher<KeyguardManager>() {
@Override
- public KeyguardManager createService() {
+ public KeyguardManager createService() throws ServiceNotFoundException {
return new KeyguardManager();
}});
@@ -336,17 +338,17 @@
registerService(Context.LOCATION_SERVICE, LocationManager.class,
new CachedServiceFetcher<LocationManager>() {
@Override
- public LocationManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
+ public LocationManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE);
return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
}});
registerService(Context.NETWORK_POLICY_SERVICE, NetworkPolicyManager.class,
new CachedServiceFetcher<NetworkPolicyManager>() {
@Override
- public NetworkPolicyManager createService(ContextImpl ctx) {
+ public NetworkPolicyManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new NetworkPolicyManager(ctx, INetworkPolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)));
+ ServiceManager.getServiceOrThrow(Context.NETWORK_POLICY_SERVICE)));
}});
registerService(Context.NOTIFICATION_SERVICE, NotificationManager.class,
@@ -368,8 +370,8 @@
registerService(Context.NSD_SERVICE, NsdManager.class,
new CachedServiceFetcher<NsdManager>() {
@Override
- public NsdManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.NSD_SERVICE);
+ public NsdManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.NSD_SERVICE);
INsdManager service = INsdManager.Stub.asInterface(b);
return new NsdManager(ctx.getOuterContext(), service);
}});
@@ -377,12 +379,9 @@
registerService(Context.POWER_SERVICE, PowerManager.class,
new CachedServiceFetcher<PowerManager>() {
@Override
- public PowerManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
+ public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
- if (service == null) {
- Log.wtf(TAG, "Failed to get power manager service.");
- }
return new PowerManager(ctx.getOuterContext(),
service, ctx.mMainThread.getHandler());
}});
@@ -390,19 +389,16 @@
registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
new CachedServiceFetcher<RecoverySystem>() {
@Override
- public RecoverySystem createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.RECOVERY_SERVICE);
+ public RecoverySystem createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.RECOVERY_SERVICE);
IRecoverySystem service = IRecoverySystem.Stub.asInterface(b);
- if (service == null) {
- Log.wtf(TAG, "Failed to get recovery service.");
- }
return new RecoverySystem(service);
}});
registerService(Context.SEARCH_SERVICE, SearchManager.class,
new CachedServiceFetcher<SearchManager>() {
@Override
- public SearchManager createService(ContextImpl ctx) {
+ public SearchManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new SearchManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler());
}});
@@ -425,7 +421,7 @@
registerService(Context.STORAGE_SERVICE, StorageManager.class,
new CachedServiceFetcher<StorageManager>() {
@Override
- public StorageManager createService(ContextImpl ctx) {
+ public StorageManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper());
}});
@@ -460,23 +456,23 @@
registerService(Context.UI_MODE_SERVICE, UiModeManager.class,
new CachedServiceFetcher<UiModeManager>() {
@Override
- public UiModeManager createService(ContextImpl ctx) {
+ public UiModeManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new UiModeManager();
}});
registerService(Context.USB_SERVICE, UsbManager.class,
new CachedServiceFetcher<UsbManager>() {
@Override
- public UsbManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.USB_SERVICE);
+ public UsbManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.USB_SERVICE);
return new UsbManager(ctx, IUsbManager.Stub.asInterface(b));
}});
registerService(Context.SERIAL_SERVICE, SerialManager.class,
new CachedServiceFetcher<SerialManager>() {
@Override
- public SerialManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.SERIAL_SERVICE);
+ public SerialManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.SERIAL_SERVICE);
return new SerialManager(ctx, ISerialManager.Stub.asInterface(b));
}});
@@ -498,8 +494,8 @@
registerService(Context.WIFI_SERVICE, WifiManager.class,
new CachedServiceFetcher<WifiManager>() {
@Override
- public WifiManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);
+ public WifiManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE);
IWifiManager service = IWifiManager.Stub.asInterface(b);
return new WifiManager(ctx.getOuterContext(), service,
ConnectivityThread.getInstanceLooper());
@@ -508,8 +504,8 @@
registerService(Context.WIFI_P2P_SERVICE, WifiP2pManager.class,
new StaticServiceFetcher<WifiP2pManager>() {
@Override
- public WifiP2pManager createService() {
- IBinder b = ServiceManager.getService(Context.WIFI_P2P_SERVICE);
+ public WifiP2pManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_P2P_SERVICE);
IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
return new WifiP2pManager(service);
}});
@@ -517,20 +513,17 @@
registerService(Context.WIFI_NAN_SERVICE, WifiNanManager.class,
new StaticServiceFetcher<WifiNanManager>() {
@Override
- public WifiNanManager createService() {
- IBinder b = ServiceManager.getService(Context.WIFI_NAN_SERVICE);
+ public WifiNanManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_NAN_SERVICE);
IWifiNanManager service = IWifiNanManager.Stub.asInterface(b);
- if (service == null) {
- return null;
- }
return new WifiNanManager(service);
}});
registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class,
new CachedServiceFetcher<WifiScanner>() {
@Override
- public WifiScanner createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.WIFI_SCANNING_SERVICE);
+ public WifiScanner createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SCANNING_SERVICE);
IWifiScanner service = IWifiScanner.Stub.asInterface(b);
return new WifiScanner(ctx.getOuterContext(), service,
ConnectivityThread.getInstanceLooper());
@@ -539,8 +532,8 @@
registerService(Context.WIFI_RTT_SERVICE, RttManager.class,
new CachedServiceFetcher<RttManager>() {
@Override
- public RttManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.WIFI_RTT_SERVICE);
+ public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_SERVICE);
IRttManager service = IRttManager.Stub.asInterface(b);
return new RttManager(ctx.getOuterContext(), service,
ConnectivityThread.getInstanceLooper());
@@ -549,8 +542,8 @@
registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
new CachedServiceFetcher<EthernetManager>() {
@Override
- public EthernetManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.ETHERNET_SERVICE);
+ public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.ETHERNET_SERVICE);
IEthernetManager service = IEthernetManager.Stub.asInterface(b);
return new EthernetManager(ctx.getOuterContext(), service);
}});
@@ -565,8 +558,8 @@
registerService(Context.USER_SERVICE, UserManager.class,
new CachedServiceFetcher<UserManager>() {
@Override
- public UserManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.USER_SERVICE);
+ public UserManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.USER_SERVICE);
IUserManager service = IUserManager.Stub.asInterface(b);
return new UserManager(ctx, service);
}});
@@ -574,8 +567,8 @@
registerService(Context.APP_OPS_SERVICE, AppOpsManager.class,
new CachedServiceFetcher<AppOpsManager>() {
@Override
- public AppOpsManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
+ public AppOpsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.APP_OPS_SERVICE);
IAppOpsService service = IAppOpsService.Stub.asInterface(b);
return new AppOpsManager(ctx, service);
}});
@@ -597,8 +590,8 @@
registerService(Context.RESTRICTIONS_SERVICE, RestrictionsManager.class,
new CachedServiceFetcher<RestrictionsManager>() {
@Override
- public RestrictionsManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.RESTRICTIONS_SERVICE);
+ public RestrictionsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.RESTRICTIONS_SERVICE);
IRestrictionsManager service = IRestrictionsManager.Stub.asInterface(b);
return new RestrictionsManager(ctx, service);
}});
@@ -606,8 +599,8 @@
registerService(Context.PRINT_SERVICE, PrintManager.class,
new CachedServiceFetcher<PrintManager>() {
@Override
- public PrintManager createService(ContextImpl ctx) {
- IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE);
+ public PrintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder iBinder = ServiceManager.getServiceOrThrow(Context.PRINT_SERVICE);
IPrintManager service = IPrintManager.Stub.asInterface(iBinder);
return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(),
UserHandle.getAppId(Process.myUid()));
@@ -616,7 +609,7 @@
registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
new CachedServiceFetcher<ConsumerIrManager>() {
@Override
- public ConsumerIrManager createService(ContextImpl ctx) {
+ public ConsumerIrManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new ConsumerIrManager(ctx);
}});
@@ -630,16 +623,16 @@
registerService(Context.TRUST_SERVICE, TrustManager.class,
new StaticServiceFetcher<TrustManager>() {
@Override
- public TrustManager createService() {
- IBinder b = ServiceManager.getService(Context.TRUST_SERVICE);
+ public TrustManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE);
return new TrustManager(b);
}});
registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class,
new CachedServiceFetcher<FingerprintManager>() {
@Override
- public FingerprintManager createService(ContextImpl ctx) {
- IBinder binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE);
+ public FingerprintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder binder = ServiceManager.getServiceOrThrow(Context.FINGERPRINT_SERVICE);
IFingerprintService service = IFingerprintService.Stub.asInterface(binder);
return new FingerprintManager(ctx.getOuterContext(), service);
}});
@@ -647,8 +640,8 @@
registerService(Context.TV_INPUT_SERVICE, TvInputManager.class,
new StaticServiceFetcher<TvInputManager>() {
@Override
- public TvInputManager createService() {
- IBinder iBinder = ServiceManager.getService(Context.TV_INPUT_SERVICE);
+ public TvInputManager createService() throws ServiceNotFoundException {
+ IBinder iBinder = ServiceManager.getServiceOrThrow(Context.TV_INPUT_SERVICE);
ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder);
return new TvInputManager(service, UserHandle.myUserId());
}});
@@ -656,15 +649,15 @@
registerService(Context.NETWORK_SCORE_SERVICE, NetworkScoreManager.class,
new CachedServiceFetcher<NetworkScoreManager>() {
@Override
- public NetworkScoreManager createService(ContextImpl ctx) {
+ public NetworkScoreManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new NetworkScoreManager(ctx);
}});
registerService(Context.USAGE_STATS_SERVICE, UsageStatsManager.class,
new CachedServiceFetcher<UsageStatsManager>() {
@Override
- public UsageStatsManager createService(ContextImpl ctx) {
- IBinder iBinder = ServiceManager.getService(Context.USAGE_STATS_SERVICE);
+ public UsageStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder iBinder = ServiceManager.getServiceOrThrow(Context.USAGE_STATS_SERVICE);
IUsageStatsManager service = IUsageStatsManager.Stub.asInterface(iBinder);
return new UsageStatsManager(ctx.getOuterContext(), service);
}});
@@ -672,23 +665,23 @@
registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class,
new CachedServiceFetcher<NetworkStatsManager>() {
@Override
- public NetworkStatsManager createService(ContextImpl ctx) {
+ public NetworkStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new NetworkStatsManager(ctx.getOuterContext());
}});
registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
new StaticServiceFetcher<JobScheduler>() {
@Override
- public JobScheduler createService() {
- IBinder b = ServiceManager.getService(Context.JOB_SCHEDULER_SERVICE);
+ public JobScheduler createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.JOB_SCHEDULER_SERVICE);
return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b));
}});
registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,
new StaticServiceFetcher<PersistentDataBlockManager>() {
@Override
- public PersistentDataBlockManager createService() {
- IBinder b = ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ public PersistentDataBlockManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.PERSISTENT_DATA_BLOCK_SERVICE);
IPersistentDataBlockService persistentDataBlockService =
IPersistentDataBlockService.Stub.asInterface(b);
if (persistentDataBlockService != null) {
@@ -709,19 +702,16 @@
registerService(Context.APPWIDGET_SERVICE, AppWidgetManager.class,
new CachedServiceFetcher<AppWidgetManager>() {
@Override
- public AppWidgetManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
+ public AppWidgetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.APPWIDGET_SERVICE);
return new AppWidgetManager(ctx, IAppWidgetService.Stub.asInterface(b));
}});
registerService(Context.MIDI_SERVICE, MidiManager.class,
new CachedServiceFetcher<MidiManager>() {
@Override
- public MidiManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.MIDI_SERVICE);
- if (b == null) {
- return null;
- }
+ public MidiManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.MIDI_SERVICE);
return new MidiManager(IMidiManager.Stub.asInterface(b));
}});
@@ -735,43 +725,41 @@
registerService(Context.HARDWARE_PROPERTIES_SERVICE, HardwarePropertiesManager.class,
new CachedServiceFetcher<HardwarePropertiesManager>() {
@Override
- public HardwarePropertiesManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.HARDWARE_PROPERTIES_SERVICE);
- IHardwarePropertiesManager service =
- IHardwarePropertiesManager.Stub.asInterface(b);
- if (service == null) {
- Log.wtf(TAG, "Failed to get hardwareproperties service.");
- return null;
- }
- return new HardwarePropertiesManager(ctx, service);
+ public HardwarePropertiesManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.HARDWARE_PROPERTIES_SERVICE);
+ IHardwarePropertiesManager service =
+ IHardwarePropertiesManager.Stub.asInterface(b);
+ return new HardwarePropertiesManager(ctx, service);
}});
registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class,
new CachedServiceFetcher<SoundTriggerManager>() {
@Override
- public SoundTriggerManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE);
+ public SoundTriggerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.SOUND_TRIGGER_SERVICE);
return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
}});
registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class,
new CachedServiceFetcher<ShortcutManager>() {
@Override
- public ShortcutManager createService(ContextImpl ctx) {
- return new ShortcutManager(ctx);
+ public ShortcutManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.SHORTCUT_SERVICE);
+ return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
}});
registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
new CachedServiceFetcher<SystemHealthManager>() {
@Override
- public SystemHealthManager createService(ContextImpl ctx) {
- return new SystemHealthManager();
+ public SystemHealthManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME);
+ return new SystemHealthManager(IBatteryStats.Stub.asInterface(b));
}});
registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class,
new CachedServiceFetcher<ContextHubManager>() {
@Override
- public ContextHubManager createService(ContextImpl ctx) {
+ public ContextHubManager createService(ContextImpl ctx) throws ServiceNotFoundException {
return new ContextHubManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler().getLooper());
}});
@@ -836,14 +824,18 @@
// Fetch or create the service.
Object service = cache[mCacheIndex];
if (service == null) {
- service = createService(ctx);
- cache[mCacheIndex] = service;
+ try {
+ service = createService(ctx);
+ cache[mCacheIndex] = service;
+ } catch (ServiceNotFoundException e) {
+ Log.w(TAG, e.getMessage(), e);
+ }
}
return (T)service;
}
}
- public abstract T createService(ContextImpl ctx);
+ public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
}
/**
@@ -857,13 +849,17 @@
public final T getService(ContextImpl unused) {
synchronized (StaticServiceFetcher.this) {
if (mCachedInstance == null) {
- mCachedInstance = createService();
+ try {
+ mCachedInstance = createService();
+ } catch (ServiceNotFoundException e) {
+ Log.w(TAG, e.getMessage(), e);
+ }
}
return mCachedInstance;
}
}
- public abstract T createService();
+ public abstract T createService() throws ServiceNotFoundException;
}
/**
@@ -886,13 +882,16 @@
// it's the application context very early in app initialization. In both these
// cases, the passed-in ContextImpl will not be freed, so it's safe to pass it
// to the service. http://b/27532714 .
- mCachedInstance = createService(appContext != null ? appContext : ctx);
+ try {
+ mCachedInstance = createService(appContext != null ? appContext : ctx);
+ } catch (ServiceNotFoundException e) {
+ Log.w(TAG, e.getMessage(), e);
+ }
}
return mCachedInstance;
}
}
- public abstract T createService(Context applicationContext);
+ public abstract T createService(Context applicationContext) throws ServiceNotFoundException;
}
-
}
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 69e8df8..0046b0e 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -22,6 +22,7 @@
import android.content.res.Configuration;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -123,9 +124,9 @@
private IUiModeManager mService;
- /*package*/ UiModeManager() {
+ /*package*/ UiModeManager() throws ServiceNotFoundException {
mService = IUiModeManager.Stub.asInterface(
- ServiceManager.getService(Context.UI_MODE_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.UI_MODE_SERVICE));
}
/**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 20cbde1..6e44662 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1680,13 +1680,13 @@
* Only the OS itself may use this method.
* @hide
*/
- public boolean isWallpaperBackupEligible() {
+ public boolean isWallpaperBackupEligible(int which) {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
}
try {
- return sGlobals.mService.isWallpaperBackupEligible(mContext.getUserId());
+ return sGlobals.mService.isWallpaperBackupEligible(which, mContext.getUserId());
} catch (RemoteException e) {
Log.e(TAG, "Exception querying wallpaper backup eligibility: " + e.getMessage());
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3a2038f..6ac7132 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -46,6 +46,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.provider.ContactsContract.Directory;
import android.provider.Settings;
import android.security.Credentials;
@@ -99,28 +100,20 @@
private final IDevicePolicyManager mService;
private final boolean mParentInstance;
- private DevicePolicyManager(Context context, boolean parentInstance) {
- this(context,
- IDevicePolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)),
- parentInstance);
+ /** @hide */
+ public DevicePolicyManager(Context context, IDevicePolicyManager service) {
+ this(context, service, false);
}
/** @hide */
@VisibleForTesting
- protected DevicePolicyManager(
- Context context, IDevicePolicyManager service, boolean parentInstance) {
+ protected DevicePolicyManager(Context context, IDevicePolicyManager service,
+ boolean parentInstance) {
mContext = context;
mService = service;
mParentInstance = parentInstance;
}
- /** @hide */
- public static DevicePolicyManager create(Context context) {
- DevicePolicyManager me = new DevicePolicyManager(context, false);
- return me.mService != null ? me : null;
- }
-
/** @hide test will override it. */
@VisibleForTesting
protected int myUserId() {
@@ -6054,7 +6047,7 @@
if (!mService.isManagedProfile(admin)) {
throw new SecurityException("The current user does not have a parent profile.");
}
- return new DevicePolicyManager(mContext, true);
+ return new DevicePolicyManager(mContext, mService, true);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6146,7 +6139,7 @@
throw new SecurityException("The user " + uInfo.id
+ " does not have a parent profile.");
}
- return new DevicePolicyManager(mContext, true);
+ return new DevicePolicyManager(mContext, mService, true);
}
/**
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 7961a72..e805fab 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -34,6 +34,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
/**
@@ -95,10 +96,10 @@
/**
* {@hide}
*/
- public NetworkStatsManager(Context context) {
+ public NetworkStatsManager(Context context) throws ServiceNotFoundException {
mContext = context;
mService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
}
/**
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 8e659e0..f53ca94 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -31,6 +31,8 @@
*/
public class OobData implements Parcelable {
private byte[] securityManagerTk;
+ private byte[] leSecureConnectionsConfirmation;
+ private byte[] leSecureConnectionsRandom;
public byte[] getSecurityManagerTk() {
return securityManagerTk;
@@ -45,10 +47,28 @@
this.securityManagerTk = securityManagerTk;
}
+ public byte[] getLeSecureConnectionsConfirmation() {
+ return leSecureConnectionsConfirmation;
+ }
+
+ public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) {
+ this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation;
+ }
+
+ public byte[] getLeSecureConnectionsRandom() {
+ return leSecureConnectionsRandom;
+ }
+
+ public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) {
+ this.leSecureConnectionsRandom = leSecureConnectionsRandom;
+ }
+
public OobData() { }
private OobData(Parcel in) {
securityManagerTk = in.createByteArray();
+ leSecureConnectionsConfirmation = in.createByteArray();
+ leSecureConnectionsRandom = in.createByteArray();
}
public int describeContents() {
@@ -58,6 +78,8 @@
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeByteArray(securityManagerTk);
+ out.writeByteArray(leSecureConnectionsConfirmation);
+ out.writeByteArray(leSecureConnectionsRandom);
}
public static final Parcelable.Creator<OobData> CREATOR
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 7244227..c28172c 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -16,12 +16,11 @@
package android.content;
-import android.content.Context;
+import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import java.util.ArrayList;
@@ -49,10 +48,8 @@
* @see android.content.Context#getSystemService
*/
public class ClipboardManager extends android.text.ClipboardManager {
- private final static Object sStaticLock = new Object();
- private static IClipboard sService;
-
private final Context mContext;
+ private final IClipboard mService;
private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners
= new ArrayList<OnPrimaryClipChangedListener>();
@@ -93,20 +90,11 @@
void onPrimaryClipChanged();
}
- static private IClipboard getService() {
- synchronized (sStaticLock) {
- if (sService != null) {
- return sService;
- }
- IBinder b = ServiceManager.getService("clipboard");
- sService = IClipboard.Stub.asInterface(b);
- return sService;
- }
- }
-
/** {@hide} */
- public ClipboardManager(Context context, Handler handler) {
+ public ClipboardManager(Context context, Handler handler) throws ServiceNotFoundException {
mContext = context;
+ mService = IClipboard.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.CLIPBOARD_SERVICE));
}
/**
@@ -120,7 +108,7 @@
if (clip != null) {
clip.prepareToLeaveProcess(true);
}
- getService().setPrimaryClip(clip, mContext.getOpPackageName());
+ mService.setPrimaryClip(clip, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -131,7 +119,7 @@
*/
public ClipData getPrimaryClip() {
try {
- return getService().getPrimaryClip(mContext.getOpPackageName());
+ return mService.getPrimaryClip(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -143,7 +131,7 @@
*/
public ClipDescription getPrimaryClipDescription() {
try {
- return getService().getPrimaryClipDescription(mContext.getOpPackageName());
+ return mService.getPrimaryClipDescription(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -154,7 +142,7 @@
*/
public boolean hasPrimaryClip() {
try {
- return getService().hasPrimaryClip(mContext.getOpPackageName());
+ return mService.hasPrimaryClip(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -164,7 +152,7 @@
synchronized (mPrimaryClipChangedListeners) {
if (mPrimaryClipChangedListeners.size() == 0) {
try {
- getService().addPrimaryClipChangedListener(
+ mService.addPrimaryClipChangedListener(
mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -179,7 +167,7 @@
mPrimaryClipChangedListeners.remove(what);
if (mPrimaryClipChangedListeners.size() == 0) {
try {
- getService().removePrimaryClipChangedListener(
+ mService.removePrimaryClipChangedListener(
mPrimaryClipChangedServiceListener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -217,7 +205,7 @@
@Deprecated
public boolean hasText() {
try {
- return getService().hasClipboardText(mContext.getOpPackageName());
+ return mService.hasClipboardText(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
index 953b051..f47ad1f 100644
--- a/core/java/android/content/pm/IntentFilterVerificationInfo.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -60,9 +60,9 @@
mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
}
- public IntentFilterVerificationInfo(String packageName, ArrayList<String> domains) {
+ public IntentFilterVerificationInfo(String packageName, ArraySet<String> domains) {
mPackageName = packageName;
- mDomains.addAll(domains);
+ mDomains = domains;
mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
}
@@ -96,8 +96,8 @@
return mDomains;
}
- public void setDomains(ArrayList<String> list) {
- mDomains = new ArraySet<>(list);
+ public void setDomains(ArraySet<String> list) {
+ mDomains = list;
}
public String getDomainsString() {
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index 9fa1c3f..b221e16 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
/**
@@ -40,10 +41,10 @@
/**
* @hide to prevent subclassing from outside of the framework
*/
- public ConsumerIrManager(Context context) {
+ public ConsumerIrManager(Context context) throws ServiceNotFoundException {
mPackageName = context.getPackageName();
mService = IConsumerIrService.Stub.asInterface(
- ServiceManager.getService(Context.CONSUMER_IR_SERVICE));
+ ServiceManager.getServiceOrThrow(Context.CONSUMER_IR_SERVICE));
}
/**
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index c23bd5b..b10c341 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -286,23 +286,29 @@
}
@Override
- public synchronized void abortCaptures() throws CameraAccessException {
- checkNotClosed();
+ public void abortCaptures() throws CameraAccessException {
+ synchronized (this) {
+ checkNotClosed();
- if (DEBUG) {
- Log.v(TAG, mIdString + "abortCaptures");
+ if (DEBUG) {
+ Log.v(TAG, mIdString + "abortCaptures");
+ }
+
+ if (mAborting) {
+ Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing");
+ return;
+ }
+
+ mAborting = true;
+ mAbortDrainer.taskStarted();
}
- if (mAborting) {
- Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing");
- return;
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ synchronized (this) {
+ mDeviceImpl.flush();
+ // The next BUSY -> IDLE set of transitions will mark the end of the abort.
+ }
}
-
- mAborting = true;
- mAbortDrainer.taskStarted();
-
- mDeviceImpl.flush();
- // The next BUSY -> IDLE set of transitions will mark the end of the abort.
}
@Override
@@ -330,78 +336,86 @@
* @see CameraCaptureSession#close
*/
@Override
- public synchronized void replaceSessionClose() {
- /*
- * In order for creating new sessions to be fast, the new session should be created
- * before the old session is closed.
- *
- * Otherwise the old session will always unconfigure if there is no new session to
- * replace it.
- *
- * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt
- * to skip unconfigure if a new session is created before the captures are all drained,
- * but this would introduce nondeterministic behavior.
- */
+ public void replaceSessionClose() {
+ synchronized (this) {
+ /*
+ * In order for creating new sessions to be fast, the new session should be created
+ * before the old session is closed.
+ *
+ * Otherwise the old session will always unconfigure if there is no new session to
+ * replace it.
+ *
+ * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt
+ * to skip unconfigure if a new session is created before the captures are all drained,
+ * but this would introduce nondeterministic behavior.
+ */
- if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose");
+ if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose");
- // Set up fast shutdown. Possible alternative paths:
- // - This session is active, so close() below starts the shutdown drain
- // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
- // - This session is already closed and has executed the idle drain listener, and
- // configureOutputsChecked(null) has already been called.
- //
- // Do not call configureOutputsChecked(null) going forward, since it would race with the
- // configuration for the new session. If it was already called, then we don't care, since it
- // won't get called again.
- mSkipUnconfigure = true;
-
+ // Set up fast shutdown. Possible alternative paths:
+ // - This session is active, so close() below starts the shutdown drain
+ // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
+ // - This session is already closed and has executed the idle drain listener, and
+ // configureOutputsChecked(null) has already been called.
+ //
+ // Do not call configureOutputsChecked(null) going forward, since it would race with the
+ // configuration for the new session. If it was already called, then we don't care,
+ // since it won't get called again.
+ mSkipUnconfigure = true;
+ }
close();
}
@Override
- public synchronized void close() {
+ public void close() {
+ synchronized (this) {
+ if (mClosed) {
+ if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
+ return;
+ }
- if (mClosed) {
- if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
- return;
+ if (DEBUG) Log.v(TAG, mIdString + "close - first time");
+
+ mClosed = true;
}
- if (DEBUG) Log.v(TAG, mIdString + "close - first time");
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ synchronized (this) {
+ /*
+ * Flush out any repeating request. Since camera is closed, no new requests
+ * can be queued, and eventually the entire request queue will be drained.
+ *
+ * If the camera device was already closed, short circuit and do nothing; since
+ * no more internal device callbacks will fire anyway.
+ *
+ * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure
+ * the camera. Once that's done, fire #onClosed.
+ */
+ try {
+ mDeviceImpl.stopRepeating();
+ } catch (IllegalStateException e) {
+ // OK: Camera device may already be closed, nothing else to do
- mClosed = true;
+ // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
+ // or just suppress the ISE only and rely onClosed.
+ // Also skip any of the draining work if this is already closed.
- /*
- * Flush out any repeating request. Since camera is closed, no new requests
- * can be queued, and eventually the entire request queue will be drained.
- *
- * If the camera device was already closed, short circuit and do nothing; since
- * no more internal device callbacks will fire anyway.
- *
- * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure the
- * camera. Once that's done, fire #onClosed.
- */
- try {
- mDeviceImpl.stopRepeating();
- } catch (IllegalStateException e) {
- // OK: Camera device may already be closed, nothing else to do
+ // Short-circuit; queue callback immediately and return
+ mStateCallback.onClosed(this);
+ return;
+ } catch (CameraAccessException e) {
+ // OK: close does not throw checked exceptions.
+ Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
- // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
- // or just suppress the ISE only and rely onClosed.
- // Also skip any of the draining work if this is already closed.
-
- // Short-circuit; queue callback immediately and return
- mStateCallback.onClosed(this);
- return;
- } catch (CameraAccessException e) {
- // OK: close does not throw checked exceptions.
- Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
-
- // TODO: call onError instead of onClosed if this happens
+ // TODO: call onError instead of onClosed if this happens
+ }
+ }
}
- // If no sequences are pending, fire #onClosed immediately
- mSequenceDrainer.beginDrain();
+ synchronized (this) {
+ // If no sequences are pending, fire #onClosed immediately
+ mSequenceDrainer.beginDrain();
+ }
}
/**
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 803337b..2b0593f 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -33,6 +33,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Vibrator;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
@@ -225,8 +226,12 @@
public static InputManager getInstance() {
synchronized (InputManager.class) {
if (sInstance == null) {
- IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
- sInstance = new InputManager(IInputManager.Stub.asInterface(b));
+ try {
+ sInstance = new InputManager(IInputManager.Stub
+ .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
+ } catch (ServiceNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
}
return sInstance;
}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 3bc1562..2aed53c 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -18,10 +18,10 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
/**
@@ -38,7 +38,7 @@
private static final String TAG = "ContextHubManager";
private final Looper mMainLooper;
- private IContextHubService mContextHubService;
+ private final IContextHubService mService;
private Callback mCallback;
private Handler mCallbackHandler;
@@ -92,13 +92,11 @@
* @return array of context hub handles
*/
public int[] getContextHubHandles() {
- int[] retVal = null;
try {
- retVal = getBinder().getContextHubHandles();
+ return mService.getContextHubHandles();
} catch (RemoteException e) {
- Log.w(TAG, "Could not fetch context hub handles : " + e);
+ throw e.rethrowFromSystemServer();
}
- return retVal;
}
/**
@@ -110,14 +108,11 @@
* @see ContextHubInfo
*/
public ContextHubInfo getContextHubInfo(int hubHandle) {
- ContextHubInfo retVal = null;
try {
- retVal = getBinder().getContextHubInfo(hubHandle);
+ return mService.getContextHubInfo(hubHandle);
} catch (RemoteException e) {
- Log.w(TAG, "Could not fetch context hub info :" + e);
+ throw e.rethrowFromSystemServer();
}
-
- return retVal;
}
/**
@@ -132,19 +127,11 @@
* @see NanoApp
*/
public int loadNanoApp(int hubHandle, NanoApp app) {
- int retVal = -1;
-
- if (app == null) {
- return retVal;
- }
-
try {
- retVal = getBinder().loadNanoApp(hubHandle, app);
+ return mService.loadNanoApp(hubHandle, app);
} catch (RemoteException e) {
- Log.w(TAG, "Could not load nanoApp :" + e);
+ throw e.rethrowFromSystemServer();
}
-
- return retVal;
}
/**
@@ -155,15 +142,11 @@
* @return int 0 on success, -1 otherwise
*/
public int unloadNanoApp(int nanoAppHandle) {
- int retVal = -1;
-
try {
- retVal = getBinder().unloadNanoApp(nanoAppHandle);
+ return mService.unloadNanoApp(nanoAppHandle);
} catch (RemoteException e) {
- Log.w(TAG, "Could not fetch unload nanoApp :" + e);
+ throw e.rethrowFromSystemServer();
}
-
- return retVal;
}
/**
@@ -175,15 +158,11 @@
* @see NanoAppInstanceInfo
*/
public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
- NanoAppInstanceInfo retVal = null;
-
try {
- retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
+ return mService.getNanoAppInstanceInfo(nanoAppHandle);
} catch (RemoteException e) {
- Log.w(TAG, "Could not fetch nanoApp info :" + e);
+ throw e.rethrowFromSystemServer();
}
-
- return retVal;
}
/**
@@ -197,13 +176,11 @@
* @return int[] Array of handles to any found nano apps
*/
public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
- int[] retVal = null;
try {
- retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
+ return mService.findNanoAppOnHub(hubHandle, filter);
} catch (RemoteException e) {
- Log.w(TAG, "Could not query nanoApp instance :" + e);
+ throw e.rethrowFromSystemServer();
}
- return retVal;
}
/**
@@ -218,19 +195,11 @@
* @return int 0 on success, -1 otherwise
*/
public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
- int retVal = -1;
-
- if (message == null || message.getData() == null) {
- Log.w(TAG, "null ptr");
- return retVal;
- }
try {
- retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
+ return mService.sendMessage(hubHandle, nanoAppHandle, message);
} catch (RemoteException e) {
- Log.w(TAG, "Could not send message :" + e.toString());
+ throw e.rethrowFromSystemServer();
}
-
- return retVal;
}
/**
@@ -318,7 +287,7 @@
return 0;
}
- private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
+ private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
@Override
public void onMessageReceipt(final int hubId, final int nanoAppId,
final ContextHubMessage message) {
@@ -346,29 +315,17 @@
}
};
- /** @hide */
- public ContextHubManager(Context context, Looper mainLooper) {
+ /** @throws ServiceNotFoundException
+ * @hide */
+ public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException {
mMainLooper = mainLooper;
+ mService = IContextHubService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(ContextHubService.CONTEXTHUB_SERVICE));
- IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
- if (b != null) {
- mContextHubService = IContextHubService.Stub.asInterface(b);
-
- try {
- getBinder().registerCallback(mClientCallback);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not register callback:" + e);
- }
-
- } else {
- Log.w(TAG, "failed to getService");
+ try {
+ mService.registerCallback(mClientCallback);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not register callback:" + e);
}
}
-
- private IContextHubService getBinder() throws RemoteException {
- if (mContextHubService == null) {
- throw new RemoteException("Service not connected.");
- }
- return mContextHubService;
- }
}
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 062c958..893ed3f 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -154,6 +154,9 @@
Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle);
return -1;
}
+ if (app == null) {
+ return -1;
+ }
int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE];
msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle;
@@ -240,6 +243,11 @@
throws RemoteException {
checkPermissions();
+ if (msg == null || msg.getData() == null) {
+ Log.w(TAG, "null ptr");
+ return -1;
+ }
+
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle;
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 01c160f..c2286ad 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -23,9 +23,9 @@
import android.content.Context;
import android.content.Intent;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
/**
@@ -127,10 +127,10 @@
private final INetworkScoreService mService;
/** @hide */
- public NetworkScoreManager(Context context) {
+ public NetworkScoreManager(Context context) throws ServiceNotFoundException {
mContext = context;
- IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE);
- mService = INetworkScoreService.Stub.asInterface(iBinder);
+ mService = INetworkScoreService.Stub
+ .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_SCORE_SERVICE));
}
/**
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index d39968a..252385f 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,11 +16,6 @@
package android.os;
-import android.content.Context;
-import android.os.BatteryProperty;
-import android.os.IBatteryPropertiesRegistrar;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import com.android.internal.app.IBatteryStats;
/**
@@ -218,6 +213,13 @@
ServiceManager.getService("batteryproperties"));
}
+ /** {@hide} */
+ public BatteryManager(IBatteryStats batteryStats,
+ IBatteryPropertiesRegistrar batteryPropertiesRegistrar) {
+ mBatteryStats = batteryStats;
+ mBatteryPropertiesRegistrar = batteryPropertiesRegistrar;
+ }
+
/**
* Return true if the battery is currently considered to be charging. This means that
* the device is plugged in and is supplying sufficient power that the battery level is
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 68aaa1f..91fe352 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -677,9 +677,9 @@
* <li> {@link android.app.DownloadManager.Request#setAllowedNetworkTypes
* DownloadManager.Request.setAllowedNetworkTypes}
* will disable "allow over metered" when specifying only
- * {@link android.app.DownloadManager.Request#NETWORK_WIFI}.
+ * {@link android.app.DownloadManager.Request#NETWORK_WIFI}.</li>
* <li> {@link android.app.DownloadManager} no longer allows access to raw
- * file paths.
+ * file paths.</li>
* <li> {@link android.app.Notification.Builder#setShowWhen
* Notification.Builder.setShowWhen}
* must be called explicitly to have the time shown, and various other changes in
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 2ba4aa4..640105c 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -16,10 +16,10 @@
package android.os;
-import com.android.internal.os.BinderInternal;
-
import android.util.Log;
+import com.android.internal.os.BinderInternal;
+
import java.util.HashMap;
import java.util.Map;
@@ -61,6 +61,21 @@
}
/**
+ * Returns a reference to a service with the given name, or throws
+ * {@link NullPointerException} if none is found.
+ *
+ * @hide
+ */
+ public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
+ final IBinder binder = getService(name);
+ if (binder != null) {
+ return binder;
+ } else {
+ throw new ServiceNotFoundException(name);
+ }
+ }
+
+ /**
* Place a new @a service called @a name into the service
* manager.
*
@@ -138,4 +153,17 @@
}
sCache.putAll(cache);
}
+
+ /**
+ * Exception thrown when no service published for given name. This might be
+ * thrown early during boot before certain services have published
+ * themselves.
+ *
+ * @hide
+ */
+ public static class ServiceNotFoundException extends Exception {
+ public ServiceNotFoundException(String name) {
+ super("No service published for: " + name);
+ }
+ }
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index cfd016e..06e2931 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -615,7 +615,8 @@
/**
* Specifies if a user is not allowed to enable the oem unlock setting. The default value is
- * <code>false</code>.
+ * <code>false</code>. Setting this restriction has no effect if the bootloader is already
+ * unlocked.
*
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 32e8425..7c0af25 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -21,6 +21,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import com.android.internal.app.IBatteryStats;
@@ -47,8 +48,12 @@
* @hide
*/
public SystemHealthManager() {
- mBatteryStats = IBatteryStats.Stub.asInterface(
- ServiceManager.getService(BatteryStats.SERVICE_NAME));
+ this(IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME)));
+ }
+
+ /** {@hide} */
+ public SystemHealthManager(IBatteryStats batteryStats) {
+ mBatteryStats = batteryStats;
}
/**
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c5507b9..cee7553 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -35,6 +35,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
@@ -341,7 +342,7 @@
* Constructs a StorageManager object through which an application can
* can communicate with the systems mount service.
*
- * @param tgtLooper The {@link android.os.Looper} which events will be received on.
+ * @param looper The {@link android.os.Looper} which events will be received on.
*
* <p>Applications can get instance of this class by calling
* {@link android.content.Context#getSystemService(java.lang.String)} with an argument
@@ -349,14 +350,11 @@
*
* @hide
*/
- public StorageManager(Context context, Looper looper) {
+ public StorageManager(Context context, Looper looper) throws ServiceNotFoundException {
mContext = context;
mResolver = context.getContentResolver();
mLooper = looper;
- mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
- if (mMountService == null) {
- throw new IllegalStateException("Failed to find running mount service");
- }
+ mMountService = IMountService.Stub.asInterface(ServiceManager.getServiceOrThrow("mount"));
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0b082de..bff4d7d 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6026,6 +6026,17 @@
public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled";
/**
+ * Specifies whether the screen will show an animation if screen contents are sent to the
+ * assist application (active voice interaction service).
+ *
+ * Note that the disclosure will be forced for third-party assistants or if the device
+ * does not support disabling it.
+ *
+ * @hide
+ */
+ public static final String ASSIST_DISCLOSURE_ENABLED = "assist_disclosure_enabled";
+
+ /**
* Names of the service components that the current user has explicitly allowed to
* see all of the user's notifications, separated by ':'.
*
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index cfeed51..0f92ed0 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -163,10 +163,9 @@
/**
* Retrieves available information about this device's flash lock state.
*
- * @return FLASH_LOCK_STATE_LOCKED if device bootloader is locked,
- * FLASH_LOCK_STATE_UNLOCKED if device bootloader is unlocked,
- * or FLASH_LOCK_STATE unknown if this information cannot be ascertained
- * on this device.
+ * @return {@link #FLASH_LOCK_LOCKED} if device bootloader is locked,
+ * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
+ * if this information cannot be ascertained on this device.
*/
@FlashLockState
public int getFlashLockState() {
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 3855ff3..24c119f 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -29,6 +29,9 @@
/**
* A movement method that traverses links in the text buffer and scrolls if necessary.
* Supports clicking on links with DPad Center or Enter.
+ *
+ * <p>Note: Starting from Android 8.0 (API level 25) this class no longer handles the touch
+ * clicks.
*/
public class LinkMovementMethod extends ScrollingMovementMethod {
private static final int CLICK = 1;
@@ -98,14 +101,14 @@
int padding = widget.getTotalPaddingTop() +
widget.getTotalPaddingBottom();
- int areatop = widget.getScrollY();
- int areabot = areatop + widget.getHeight() - padding;
+ int areaTop = widget.getScrollY();
+ int areaBot = areaTop + widget.getHeight() - padding;
- int linetop = layout.getLineForVertical(areatop);
- int linebot = layout.getLineForVertical(areabot);
+ int lineTop = layout.getLineForVertical(areaTop);
+ int lineBot = layout.getLineForVertical(areaBot);
- int first = layout.getLineStart(linetop);
- int last = layout.getLineEnd(linebot);
+ int first = layout.getLineStart(lineTop);
+ int last = layout.getLineEnd(lineBot);
ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);
@@ -141,46 +144,46 @@
break;
case UP:
- int beststart, bestend;
+ int bestStart, bestEnd;
- beststart = -1;
- bestend = -1;
+ bestStart = -1;
+ bestEnd = -1;
for (int i = 0; i < candidates.length; i++) {
int end = buffer.getSpanEnd(candidates[i]);
if (end < selEnd || selStart == selEnd) {
- if (end > bestend) {
- beststart = buffer.getSpanStart(candidates[i]);
- bestend = end;
+ if (end > bestEnd) {
+ bestStart = buffer.getSpanStart(candidates[i]);
+ bestEnd = end;
}
}
}
- if (beststart >= 0) {
- Selection.setSelection(buffer, bestend, beststart);
+ if (bestStart >= 0) {
+ Selection.setSelection(buffer, bestEnd, bestStart);
return true;
}
break;
case DOWN:
- beststart = Integer.MAX_VALUE;
- bestend = Integer.MAX_VALUE;
+ bestStart = Integer.MAX_VALUE;
+ bestEnd = Integer.MAX_VALUE;
for (int i = 0; i < candidates.length; i++) {
int start = buffer.getSpanStart(candidates[i]);
if (start > selStart || selStart == selEnd) {
- if (start < beststart) {
- beststart = start;
- bestend = buffer.getSpanEnd(candidates[i]);
+ if (start < bestStart) {
+ bestStart = start;
+ bestEnd = buffer.getSpanEnd(candidates[i]);
}
}
}
- if (bestend < Integer.MAX_VALUE) {
- Selection.setSelection(buffer, beststart, bestend);
+ if (bestEnd < Integer.MAX_VALUE) {
+ Selection.setSelection(buffer, bestStart, bestEnd);
return true;
}
@@ -195,8 +198,7 @@
MotionEvent event) {
int action = event.getAction();
- if (action == MotionEvent.ACTION_UP ||
- action == MotionEvent.ACTION_DOWN) {
+ if (action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
@@ -210,17 +212,12 @@
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
- ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
+ ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
- Selection.setSelection(buffer,
- buffer.getSpanStart(link[0]),
- buffer.getSpanEnd(link[0]));
- }
-
+ if (links.length != 0) {
+ Selection.setSelection(buffer,
+ buffer.getSpanStart(links[0]),
+ buffer.getSpanEnd(links[0]));
return true;
} else {
Selection.removeSelection(buffer);
diff --git a/core/java/android/util/TimedRemoteCaller.java b/core/java/android/util/TimedRemoteCaller.java
index abb2b64..100c16e 100644
--- a/core/java/android/util/TimedRemoteCaller.java
+++ b/core/java/android/util/TimedRemoteCaller.java
@@ -17,6 +17,7 @@
package android.util;
import android.os.SystemClock;
+import com.android.internal.annotations.GuardedBy;
import java.util.concurrent.TimeoutException;
@@ -29,8 +30,7 @@
* the sequence number. If the response comes within the timeout
* and its sequence number is the one sent in the method invocation,
* then the call succeeded. If the response does not come within
- * the timeout then the call failed. Older result received when
- * waiting for the result are ignored.
+ * the timeout then the call failed.
* <p>
* Typical usage is:
* </p>
@@ -66,66 +66,90 @@
public static final long DEFAULT_CALL_TIMEOUT_MILLIS = 5000;
- private static final int UNDEFINED_SEQUENCE = -1;
-
private final Object mLock = new Object();
private final long mCallTimeoutMillis;
+ /** The callbacks we are waiting for, key == sequence id, value == 1 */
+ @GuardedBy("mLock")
+ private final SparseIntArray mAwaitedCalls = new SparseIntArray(1);
+
+ /** The callbacks we received but for which the result has not yet been reported */
+ @GuardedBy("mLock")
+ private final SparseArray<T> mReceivedCalls = new SparseArray<>(1);
+
+ @GuardedBy("mLock")
private int mSequenceCounter;
- private int mReceivedSequence = UNDEFINED_SEQUENCE;
-
- private int mAwaitedSequence = UNDEFINED_SEQUENCE;
-
- private T mResult;
-
+ /**
+ * Create a new timed caller.
+ *
+ * @param callTimeoutMillis The time to wait in {@link #getResultTimed} before a timed call will
+ * be declared timed out
+ */
public TimedRemoteCaller(long callTimeoutMillis) {
mCallTimeoutMillis = callTimeoutMillis;
}
- public final int onBeforeRemoteCall() {
+ /**
+ * Indicate that a timed call will be made.
+ *
+ * @return The sequence id for the call
+ */
+ protected final int onBeforeRemoteCall() {
synchronized (mLock) {
- mAwaitedSequence = mSequenceCounter++;
- return mAwaitedSequence;
+ int sequenceId;
+ do {
+ sequenceId = mSequenceCounter++;
+ } while (mAwaitedCalls.get(sequenceId) != 0);
+
+ mAwaitedCalls.put(sequenceId, 1);
+
+ return sequenceId;
}
}
- public final T getResultTimed(int sequence) throws TimeoutException {
+ /**
+ * Indicate that the timed call has returned.
+ *
+ * @param result The result of the timed call
+ * @param sequence The sequence id of the call (from {@link #onBeforeRemoteCall()})
+ */
+ protected final void onRemoteMethodResult(T result, int sequence) {
synchronized (mLock) {
- final boolean success = waitForResultTimedLocked(sequence);
- if (!success) {
- throw new TimeoutException("No reponse for sequence: " + sequence);
- }
- T result = mResult;
- mResult = null;
- return result;
- }
- }
-
- public final void onRemoteMethodResult(T result, int sequence) {
- synchronized (mLock) {
- if (sequence == mAwaitedSequence) {
- mReceivedSequence = sequence;
- mResult = result;
+ // Do nothing if we do not await the call anymore as it must have timed out
+ boolean containedSequenceId = mAwaitedCalls.get(sequence) != 0;
+ if (containedSequenceId) {
+ mAwaitedCalls.delete(sequence);
+ mReceivedCalls.put(sequence, result);
mLock.notifyAll();
}
}
}
- private boolean waitForResultTimedLocked(int sequence) {
+ /**
+ * Wait until the timed call has returned.
+ *
+ * @param sequence The sequence id of the call (from {@link #onBeforeRemoteCall()})
+ *
+ * @return The result of the timed call (set in {@link #onRemoteMethodResult(Object, int)})
+ */
+ protected final T getResultTimed(int sequence) throws TimeoutException {
final long startMillis = SystemClock.uptimeMillis();
while (true) {
try {
- if (mReceivedSequence == sequence) {
- return true;
+ synchronized (mLock) {
+ if (mReceivedCalls.indexOfKey(sequence) >= 0) {
+ return mReceivedCalls.removeReturnOld(sequence);
+ }
+ final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+ final long waitMillis = mCallTimeoutMillis - elapsedMillis;
+ if (waitMillis <= 0) {
+ mAwaitedCalls.delete(sequence);
+ throw new TimeoutException("No response for sequence: " + sequence);
+ }
+ mLock.wait(waitMillis);
}
- final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
- final long waitMillis = mCallTimeoutMillis - elapsedMillis;
- if (waitMillis <= 0) {
- return false;
- }
- mLock.wait(waitMillis);
} catch (InterruptedException ie) {
/* ignore */
}
diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java
index 4a77af4..8d891bb 100644
--- a/core/java/android/view/SoundEffectConstants.java
+++ b/core/java/android/view/SoundEffectConstants.java
@@ -37,6 +37,8 @@
* or {@link View#FOCUS_BACKWARD}
* @return The appropriate sonification constant.
+ * @throws {@link IllegalArgumentException} when the passed direction is not one of the
+ * documented values.
*/
public static int getContantForFocusDirection(int direction) {
switch (direction) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 745da51..bb77100 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -229,7 +229,6 @@
@Override
protected void destroyHardwareResources() {
destroyHardwareLayer();
- mUpdateSurface = mSurface != null;
}
private void destroyHardwareLayer() {
@@ -376,17 +375,17 @@
}
mLayer = mAttachInfo.mThreadedRenderer.createTextureLayer();
- if (!mUpdateSurface) {
+ boolean createNewSurface = (mSurface == null);
+ if (createNewSurface) {
// Create a new SurfaceTexture for the layer.
mSurface = new SurfaceTexture(false);
mLayer.setSurfaceTexture(mSurface);
nCreateNativeWindow(mSurface);
}
mSurface.setDefaultBufferSize(getWidth(), getHeight());
-
mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
- if (mListener != null && !mUpdateSurface) {
+ if (mListener != null && createNewSurface) {
mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
}
mLayer.setLayerPaint(mLayerPaint);
@@ -745,9 +744,11 @@
"released SurfaceTexture");
}
if (mSurface != null) {
+ nDestroyNativeWindow();
mSurface.release();
}
mSurface = surfaceTexture;
+ nCreateNativeWindow(mSurface);
/*
* If the view is visible and we already made a layer, update the
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8ce9ddb..1034275 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -520,16 +520,6 @@
}
/**
- * This method should be invoked whenever the current threaded renderer
- * context should be reset.
- *
- * @param surface The surface to render
- */
- void invalidate(Surface surface) {
- updateSurface(surface);
- }
-
- /**
* Detaches the layer's surface texture from the GL context and releases
* the texture id
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c37cf56..5a7f0ff 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20656,7 +20656,6 @@
* <li>{@link #DRAG_FLAG_GLOBAL}</li>
* <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
* <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
- * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
* <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
* <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
* <li>{@link #DRAG_FLAG_OPAQUE}</li>
@@ -20674,6 +20673,9 @@
Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
return false;
}
+
+ data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
+
boolean okay = false;
Point shadowSize = new Point();
@@ -23864,7 +23866,7 @@
* on the screen.
*/
private boolean shouldDrawRoundScrollbar() {
- if (!mResources.getConfiguration().isScreenRound()) {
+ if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
return false;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2bc1d74..757727b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5539,6 +5539,10 @@
// Remember who the current drag target is pre-dispatch
final View prevDragView = mCurrentDragView;
+ if (what == DragEvent.ACTION_DROP) {
+ event.getClipData().prepareToEnterProcess();
+ }
+
// Now dispatch the drag/drop event
boolean result = mView.dispatchDragEvent(event);
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index f1fa216..0b9f9d0 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -484,6 +484,7 @@
public void switchInputMethod(boolean forwardDirection);
public void shutdown(boolean confirm);
+ public void reboot(boolean confirm);
public void rebootSafeMode(boolean confirm);
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c0c8e64..e37cf96 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -41,6 +41,7 @@
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.Trace;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;
import android.util.Log;
@@ -55,6 +56,7 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewRootImpl;
+import android.view.textservice.TextServicesManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -622,6 +624,11 @@
final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
+ InputMethodManager(Looper looper) throws ServiceNotFoundException {
+ this(IInputMethodManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE)), looper);
+ }
+
InputMethodManager(IInputMethodManager service, Looper looper) {
mService = service;
mMainLooper = looper;
@@ -638,9 +645,11 @@
public static InputMethodManager getInstance() {
synchronized (InputMethodManager.class) {
if (sInstance == null) {
- IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
- IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
- sInstance = new InputMethodManager(service, Looper.getMainLooper());
+ try {
+ sInstance = new InputMethodManager(Looper.getMainLooper());
+ } catch (ServiceNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
}
return sInstance;
}
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 89d879e..0f168f3 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -16,16 +16,16 @@
package android.view.textservice;
-import com.android.internal.textservice.ITextServicesManager;
-
import android.content.Context;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+
import java.util.Locale;
/**
@@ -66,13 +66,12 @@
private static final boolean DBG = false;
private static TextServicesManager sInstance;
- private static ITextServicesManager sService;
- private TextServicesManager() {
- if (sService == null) {
- IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE);
- sService = ITextServicesManager.Stub.asInterface(b);
- }
+ private final ITextServicesManager mService;
+
+ private TextServicesManager() throws ServiceNotFoundException {
+ mService = ITextServicesManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.TEXT_SERVICES_MANAGER_SERVICE));
}
/**
@@ -81,12 +80,15 @@
*/
public static TextServicesManager getInstance() {
synchronized (TextServicesManager.class) {
- if (sInstance != null) {
- return sInstance;
+ if (sInstance == null) {
+ try {
+ sInstance = new TextServicesManager();
+ } catch (ServiceNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
}
- sInstance = new TextServicesManager();
+ return sInstance;
}
- return sInstance;
}
/**
@@ -131,7 +133,7 @@
final SpellCheckerInfo sci;
try {
- sci = sService.getCurrentSpellChecker(null);
+ sci = mService.getCurrentSpellChecker(null);
} catch (RemoteException e) {
return null;
}
@@ -170,13 +172,13 @@
return null;
}
final SpellCheckerSession session = new SpellCheckerSession(
- sci, sService, listener, subtypeInUse);
+ sci, mService, listener, subtypeInUse);
try {
- sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
+ mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
session.getTextServicesSessionListener(),
session.getSpellCheckerSessionListener(), bundle);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
return session;
}
@@ -186,14 +188,13 @@
*/
public SpellCheckerInfo[] getEnabledSpellCheckers() {
try {
- final SpellCheckerInfo[] retval = sService.getEnabledSpellCheckers();
+ final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers();
if (DBG) {
Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null"));
}
return retval;
} catch (RemoteException e) {
- Log.e(TAG, "Error in getEnabledSpellCheckers: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -203,9 +204,9 @@
public SpellCheckerInfo getCurrentSpellChecker() {
try {
// Passing null as a locale for ICS
- return sService.getCurrentSpellChecker(null);
+ return mService.getCurrentSpellChecker(null);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -217,9 +218,9 @@
if (sci == null) {
throw new NullPointerException("SpellCheckerInfo is null.");
}
- sService.setCurrentSpellChecker(null, sci.getId());
+ mService.setCurrentSpellChecker(null, sci.getId());
} catch (RemoteException e) {
- Log.e(TAG, "Error in setCurrentSpellChecker: " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -229,17 +230,10 @@
public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
boolean allowImplicitlySelectedSubtype) {
try {
- if (sService == null) {
- // TODO: This is a workaround. Needs to investigate why sService could be null
- // here.
- Log.e(TAG, "sService is null.");
- return null;
- }
// Passing null as a locale until we support multiple enabled spell checker subtypes.
- return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
+ return mService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
} catch (RemoteException e) {
- Log.e(TAG, "Error in getCurrentSpellCheckerSubtype: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -254,9 +248,9 @@
} else {
hashCode = subtype.hashCode();
}
- sService.setCurrentSpellCheckerSubtype(null, hashCode);
+ mService.setCurrentSpellCheckerSubtype(null, hashCode);
} catch (RemoteException e) {
- Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -265,9 +259,9 @@
*/
public void setSpellCheckerEnabled(boolean enabled) {
try {
- sService.setSpellCheckerEnabled(enabled);
+ mService.setSpellCheckerEnabled(enabled);
} catch (RemoteException e) {
- Log.e(TAG, "Error in setSpellCheckerEnabled:" + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -276,10 +270,9 @@
*/
public boolean isSpellCheckerEnabled() {
try {
- return sService.isSpellCheckerEnabled();
+ return mService.isSpellCheckerEnabled();
} catch (RemoteException e) {
- Log.e(TAG, "Error in isSpellCheckerEnabled:" + e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 66b22ce..5ed6638 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1546,7 +1546,7 @@
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
case R.id.accessibilityActionScrollDown: {
- if (isEnabled() && getLastVisiblePosition() < getCount() - 1) {
+ if (isEnabled() && canScrollDown()) {
final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION);
return true;
@@ -1554,7 +1554,7 @@
} return false;
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
case R.id.accessibilityActionScrollUp: {
- if (isEnabled() && mFirstPosition > 0) {
+ if (isEnabled() && canScrollUp()) {
final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION);
return true;
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 02ee2df..6f198e7 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -16,7 +16,11 @@
package android.widget;
+import com.android.internal.R;
+import com.android.internal.widget.ExploreByTouchHelper;
+
import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -43,9 +47,8 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import com.android.internal.R;
-import com.android.internal.widget.ExploreByTouchHelper;
-
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
import java.util.Locale;
@@ -55,11 +58,16 @@
* @hide
*/
public class RadialTimePickerView extends View {
-
private static final String TAG = "RadialTimePickerView";
public static final int HOURS = 0;
public static final int MINUTES = 1;
+
+ /** @hide */
+ @IntDef({HOURS, MINUTES})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface PickerType {}
+
private static final int HOURS_INNER = 2;
private static final int SELECTOR_CIRCLE = 0;
@@ -185,8 +193,24 @@
private boolean mInputEnabled = true;
- public interface OnValueSelectedListener {
- void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance);
+ interface OnValueSelectedListener {
+ /**
+ * Called when the selected value at a given picker index has changed.
+ *
+ * @param pickerType the type of value that has changed, one of:
+ * <ul>
+ * <li>{@link #MINUTES}
+ * <li>{@link #HOURS}
+ * </ul>
+ * @param newValue the new value as minute in hour (0-59) or hour in
+ * day (0-23)
+ * @param autoAdvance when the picker type is {@link #HOURS},
+ * {@code true} to switch to the {@link #MINUTES}
+ * picker or {@code false} to stay on the current
+ * picker. No effect when picker type is
+ * {@link #MINUTES}.
+ */
+ void onValueSelected(@PickerType int pickerType, int newValue, boolean autoAdvance);
}
/**
@@ -977,7 +1001,7 @@
// Ensure we're showing the correct picker.
animatePicker(mShowHours, ANIM_DURATION_TOUCH);
- final int type;
+ final @PickerType int type;
final int newValue;
final boolean valueChanged;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a6d004f..6dafe34 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -114,6 +114,7 @@
import android.view.Choreographer;
import android.view.ContextMenu;
import android.view.DragEvent;
+import android.view.GestureDetector;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyCharacterMap;
@@ -650,6 +651,8 @@
*/
private Editor mEditor;
+ private final GestureDetector mClickableSpanOnClickGestureDetector;
+
private static final int DEVICE_PROVISIONED_UNKNOWN = 0;
private static final int DEVICE_PROVISIONED_NO = 1;
private static final int DEVICE_PROVISIONED_YES = 2;
@@ -1488,6 +1491,24 @@
if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
+
+ mClickableSpanOnClickGestureDetector = new GestureDetector(context,
+ new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (mLinksClickable && (mMovement != null) &&
+ (mMovement instanceof LinkMovementMethod
+ || (mAutoLinkMask != 0 && isTextSelectable()))) {
+ ClickableSpan[] links = ((Spannable) mText).getSpans(
+ getSelectionStart(), getSelectionEnd(), ClickableSpan.class);
+ if (links.length > 0) {
+ links[0].onClick(TextView.this);
+ return true;
+ }
+ }
+ return false;
+ }
+ });
}
private int[] parseDimensionArray(TypedArray dimens) {
@@ -8515,21 +8536,9 @@
if (mMovement != null) {
handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
}
+ handled |= mClickableSpanOnClickGestureDetector.onTouchEvent(event);
final boolean textIsSelectable = isTextSelectable();
- if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) {
- // The LinkMovementMethod which should handle taps on links has not been installed
- // on non editable text that support text selection.
- // We reproduce its behavior here to open links for these.
- ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
- getSelectionEnd(), ClickableSpan.class);
-
- if (links.length > 0) {
- links[0].onClick(this);
- handled = true;
- }
- }
-
if (touchIsFinished && (isTextEditable() || textIsSelectable)) {
// Show the IME, except when selecting in read-only text.
final InputMethodManager imm = InputMethodManager.peekInstance();
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 59cde5b..1d37a21 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -62,9 +62,6 @@
private static final int HOUR_INDEX = RadialTimePickerView.HOURS;
private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES;
- // NOT a real index for the purpose of what's showing.
- private static final int AMPM_INDEX = 2;
-
private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor};
private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha};
@@ -725,22 +722,21 @@
/** Listener for RadialTimePickerView interaction. */
private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() {
@Override
- public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
- switch (pickerIndex) {
- case HOUR_INDEX:
+ public void onValueSelected(int pickerType, int newValue, boolean autoAdvance) {
+ switch (pickerType) {
+ case RadialTimePickerView.HOURS:
final boolean isTransition = mAllowAutoAdvance && autoAdvance;
setHourInternal(newValue, true, !isTransition);
if (isTransition) {
setCurrentItemShowing(MINUTE_INDEX, true, false);
- mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes);
+
+ final int localizedHour = getLocalizedHour(newValue);
+ mDelegator.announceForAccessibility(localizedHour + ". " + mSelectMinutes);
}
break;
- case MINUTE_INDEX:
+ case RadialTimePickerView.MINUTES:
setMinuteInternal(newValue, true);
break;
- case AMPM_INDEX:
- updateAmPmLabelStates(newValue);
- break;
}
if (mOnTimeChangedListener != null) {
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 56c5cc9..2940079 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -16,10 +16,13 @@
package com.android.internal.app;
+import com.android.internal.R;
+
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
@@ -166,4 +169,41 @@
return null;
}
+ public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
+ if (assistant == null) {
+ return false;
+ }
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = context.getPackageManager().getApplicationInfo(
+ assistant.getPackageName(), 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
+ }
+
+ private static boolean isDisclosureEnabled(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
+ }
+
+ /**
+ * @return if the disclosure animation should trigger for the given assistant.
+ *
+ * Third-party assistants will always need to disclose, while the user can configure this for
+ * pre-installed assistants.
+ */
+ public static boolean shouldDisclose(Context context, ComponentName assistant) {
+ if (!allowDisablingAssistDisclosure(context)) {
+ return true;
+ }
+
+ return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant);
+ }
+
+ public static boolean allowDisablingAssistDisclosure(Context context) {
+ return context.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowDisablingAssistDisclosure);
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fef4a53..0aa3a7e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -111,7 +111,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 149 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 150 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1425,22 +1425,6 @@
mUnpluggedReportedCount = 0;
return true;
}
-
- @Override
- public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
- super.writeSummaryFromParcelLocked(out, batteryRealtime);
- out.writeLong(mCurrentReportedTotalTime);
- out.writeInt(mCurrentReportedCount);
- out.writeInt(mTrackingReportedValues ? 1 : 0);
- }
-
- @Override
- public void readSummaryFromParcelLocked(Parcel in) {
- super.readSummaryFromParcelLocked(in);
- mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
- mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
- mTrackingReportedValues = in.readInt() == 1;
- }
}
/**
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 7a4f74f..40b9ab6 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -502,21 +502,42 @@
// System server is fully AOTed and never profiled
// for profile guided compilation.
// TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
- final int dexoptNeeded = DexFile.getDexOptNeeded(
+
+ int dexoptNeeded;
+ try {
+ dexoptNeeded = DexFile.getDexOptNeeded(
classPathElement, instructionSet, "speed",
false /* newProfile */);
- if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
- dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
- sharedLibraries);
+ } catch (FileNotFoundException ignored) {
+ // Do not add to the classpath.
+ Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
+ continue;
+ } catch (IOException e) {
+ // Not fully clear what to do here as we don't know the cause of the
+ // IO exception. Add to the classpath to be conservative, but don't
+ // attempt to compile it.
+ Log.w(TAG, "Error checking classpath element for system server: "
+ + classPathElement, e);
+ dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
}
+
+ if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+ try {
+ installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
+ dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
+ sharedLibraries);
+ } catch (InstallerException e) {
+ // Ignore (but log), we need this on the classpath for fallback mode.
+ Log.w(TAG, "Failed compiling classpath element for system server: "
+ + classPathElement, e);
+ }
+ }
+
if (!sharedLibraries.isEmpty()) {
sharedLibraries += ":";
}
sharedLibraries += classPathElement;
}
- } catch (IOException | InstallerException e) {
- throw new RuntimeException("Error starting system_server", e);
} finally {
installer.disconnect();
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 9ad750d..878f3a6 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -92,8 +92,6 @@
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeProvider;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
@@ -2057,9 +2055,6 @@
}
static private final String FOCUSED_ID_TAG = "android:focusedViewId";
- static private final String ACCESSIBILITY_FOCUSED_ID_TAG = "android:accessibilityFocusedViewId";
- static private final String ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG =
- "android:accessibilityFocusedVirtualViewId";
static private final String VIEWS_TAG = "android:views";
static private final String PANELS_TAG = "android:Panels";
static private final String ACTION_BAR_TAG = "android:ActionBar";
@@ -2082,26 +2077,6 @@
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
}
- // Save the accessibility focused view ID.
- if (mDecor != null) {
- final ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();
- if (viewRootImpl != null) {
- final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost();
- if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) {
- outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId());
-
- // If we have a focused virtual node ID, save that too.
- final AccessibilityNodeInfo accessFocusedNode =
- viewRootImpl.getAccessibilityFocusedVirtualView();
- if (accessFocusedNode != null) {
- final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
- accessFocusedNode.getSourceNodeId());
- outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId);
- }
- }
- }
- }
-
// save the panels
SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
savePanelState(panelStates);
@@ -2144,13 +2119,6 @@
}
}
- // Restore the accessibility focused view.
- final int accessFocusHostViewId = savedInstanceState.getInt(
- ACCESSIBILITY_FOCUSED_ID_TAG, View.NO_ID);
- final int accessFocusVirtualViewId = savedInstanceState.getInt(
- ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, AccessibilityNodeInfo.UNDEFINED_ITEM_ID);
- tryRestoreAccessibilityFocus(accessFocusHostViewId, accessFocusVirtualViewId);
-
// Restore the panels.
SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
if (panelStates != null) {
@@ -2170,33 +2138,6 @@
}
}
- private void tryRestoreAccessibilityFocus(int hostViewId, int virtualViewId) {
- if (hostViewId != View.NO_ID && mDecor != null) {
- final View needsAccessFocus = mDecor.findViewById(hostViewId);
- if (needsAccessFocus != null) {
- if (!tryFocusingVirtualView(needsAccessFocus, virtualViewId)
- && !needsAccessFocus.requestAccessibilityFocus()) {
- Log.w(TAG, "Failed to restore focus to previously accessibility"
- + " focused view with id " + hostViewId);
- }
- } else {
- Log.w(TAG, "Previously accessibility focused view reported id " + hostViewId
- + " during save, but can't be found during restore.");
- }
- }
- }
-
- private boolean tryFocusingVirtualView(View host, int virtualViewId) {
- if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- final AccessibilityNodeProvider nodeProvider = host.getAccessibilityNodeProvider();
- if (nodeProvider != null) {
- return nodeProvider.performAction(virtualViewId,
- AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
- }
- }
- return false;
- }
-
/**
* Invoked when the panels should freeze their state.
*
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2a79d28..0e07bf8 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -288,7 +288,6 @@
public void reportFailedPasswordAttempt(int userId) {
getDevicePolicyManager().reportFailedPasswordAttempt(userId);
getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
- requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL, userId);
}
public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1550,7 +1549,8 @@
value = { STRONG_AUTH_NOT_REQUIRED,
STRONG_AUTH_REQUIRED_AFTER_BOOT,
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
- SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
+ SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
+ STRONG_AUTH_REQUIRED_AFTER_LOCKOUT})
@Retention(RetentionPolicy.SOURCE)
public @interface StrongAuthFlags {}
@@ -1581,13 +1581,12 @@
public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
/**
- * Some authentication is required because the user has entered a wrong credential.
+ * Strong auth flags that do not prevent fingerprint from being accepted as auth.
+ *
+ * If any other flags are set, fingerprint is disabled.
*/
- public static final int SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL = 0x10;
-
private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
- | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST
- | SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL;
+ | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
private final H mHandler;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 23e291f..ffa7107 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -58,21 +58,19 @@
#endif
// For both of these, err should be in the errno range (positive), not a status_t (negative)
-
-static void signalExceptionForPriorityError(JNIEnv* env, int err)
-{
+static void signalExceptionForError(JNIEnv* env, int err, int tid) {
switch (err) {
case EINVAL:
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "Invalid argument: %d", tid);
break;
case ESRCH:
- jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "Given thread %d does not exist", tid);
break;
case EPERM:
- jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
- break;
- case EACCES:
- jniThrowException(env, "java/lang/SecurityException", "No permission to set to given priority");
+ jniThrowExceptionFmt(env, "java/lang/SecurityException",
+ "No permission to modify given thread %d", tid);
break;
default:
jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
@@ -80,23 +78,27 @@
}
}
-static void signalExceptionForGroupError(JNIEnv* env, int err)
-{
+static void signalExceptionForPriorityError(JNIEnv* env, int err, int tid) {
switch (err) {
- case EINVAL:
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- break;
- case ESRCH:
- jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
- break;
- case EPERM:
- jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
- break;
case EACCES:
- jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group");
+ jniThrowExceptionFmt(env, "java/lang/SecurityException",
+ "No permission to set the priority of %d", tid);
break;
default:
- jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
+ signalExceptionForError(env, err, tid);
+ break;
+ }
+
+}
+
+static void signalExceptionForGroupError(JNIEnv* env, int err, int tid) {
+ switch (err) {
+ case EACCES:
+ jniThrowExceptionFmt(env, "java/lang/SecurityException",
+ "No permission to set the group of %d", tid);
+ break;
+ default:
+ signalExceptionForError(env, err, tid);
break;
}
}
@@ -171,7 +173,7 @@
SchedPolicy sp = (SchedPolicy) grp;
int res = set_sched_policy(tid, sp);
if (res != NO_ERROR) {
- signalExceptionForGroupError(env, -res);
+ signalExceptionForGroupError(env, -res, tid);
}
}
@@ -183,7 +185,7 @@
struct dirent *de;
if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
- signalExceptionForGroupError(env, EINVAL);
+ signalExceptionForGroupError(env, EINVAL, pid);
return;
}
@@ -219,7 +221,7 @@
if (!(d = opendir(proc_path))) {
// If the process exited on us, don't generate an exception
if (errno != ENOENT)
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
return;
}
@@ -254,7 +256,7 @@
#ifdef ENABLE_CPUSETS
int err = set_cpuset_policy(t_pid, sp);
if (err != NO_ERROR) {
- signalExceptionForGroupError(env, -err);
+ signalExceptionForGroupError(env, -err, t_pid);
break;
}
#endif
@@ -266,14 +268,14 @@
// set both cpuset and cgroup for general threads
err = set_cpuset_policy(t_pid, sp);
if (err != NO_ERROR) {
- signalExceptionForGroupError(env, -err);
+ signalExceptionForGroupError(env, -err, t_pid);
break;
}
#endif
err = set_sched_policy(t_pid, sp);
if (err != NO_ERROR) {
- signalExceptionForGroupError(env, -err);
+ signalExceptionForGroupError(env, -err, t_pid);
break;
}
@@ -285,7 +287,7 @@
{
SchedPolicy sp;
if (get_sched_policy(pid, &sp) != 0) {
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
}
return (int) sp;
}
@@ -400,7 +402,7 @@
jintArray cpus;
int pid = getpid();
if (get_sched_policy(pid, &sp) != 0) {
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
return NULL;
}
get_exclusive_cpuset_cores(sp, &cpu_set);
@@ -449,10 +451,10 @@
errno = 0;
policy = sched_getscheduler(tid);
if (errno != 0) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, tid);
}
#else
- signalExceptionForPriorityError(env, ENOSYS);
+ signalExceptionForPriorityError(env, ENOSYS, tid);
#endif
return policy;
}
@@ -466,10 +468,10 @@
param.sched_priority = pri;
int rc = sched_setscheduler(tid, policy, ¶m);
if (rc) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, tid);
}
#else
- signalExceptionForPriorityError(env, ENOSYS);
+ signalExceptionForPriorityError(env, ENOSYS, tid);
#endif
}
@@ -494,9 +496,9 @@
int rc = androidSetThreadPriority(pid, pri);
if (rc != 0) {
if (rc == INVALID_OPERATION) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, pid);
} else {
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
}
}
@@ -516,7 +518,7 @@
errno = 0;
jint pri = getpriority(PRIO_PROCESS, pid);
if (errno != 0) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, pid);
}
//ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri);
return pri;
diff --git a/core/res/res/drawable/ic_lock_power_off.xml b/core/res/res/drawable/ic_lock_power_off.xml
index 718f17e..babd1be 100644
--- a/core/res/res/drawable/ic_lock_power_off.xml
+++ b/core/res/res/drawable/ic_lock_power_off.xml
@@ -1,19 +1,25 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+ 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
+ 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
+ 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.
+ 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.
-->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_lock_power_off_alpha"
- android:tint="?attr/colorControlNormal" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M13.0,3.0l-2.0,0.0l0.0,10.0l2.0,0.0L13.0,3.0zm4.83,2.17l-1.42,1.42C17.99,7.86 19.0,9.81 19.0,12.0c0.0,3.87 -3.13,7.0 -7.0,7.0s-7.0,-3.13 -7.0,-7.0c0.0,-2.19 1.01,-4.14 2.58,-5.42L6.17,5.17C4.23,6.82 3.0,9.26 3.0,12.0c0.0,4.97 4.03,9.0 9.0,9.0s9.0,-4.03 9.0,-9.0c0.0,-2.74 -1.23,-5.18 -3.17,-6.83z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_restart.xml b/core/res/res/drawable/ic_restart.xml
new file mode 100644
index 0000000..47ac483
--- /dev/null
+++ b/core/res/res/drawable/ic_restart.xml
@@ -0,0 +1,28 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12.0,4.0L12.0,1.0L8.0,5.0l4.0,4.0L12.0,6.0c3.9,0.0 7.0,3.1 7.0,7.0c0.0,3.9 -3.1,7.0 -7.0,7.0l0.0,2.0c5.0,0.0 9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M5.0,12.9C5.0,11.0 5.8,9.2 7.2,7.9L5.8,6.4C4.0,8.1 3.0,10.5 3.0,12.9c0.0,4.0 2.7,7.6 6.5,8.7l0.5,-1.9C7.1,18.8 5.0,16.1 5.0,12.9z"/>
+</vector>
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index d12c8ba..d8dd447 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -41,7 +41,7 @@
android:visibility="gone"
style="?attr/borderlessButtonStyle"
android:textAppearance="?attr/textAppearanceButton"
- android:textColor="@color/material_deep_teal_500"
+ android:textColor="?attr/colorAccent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index ae94503..c4e8e9c 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -42,7 +42,7 @@
android:visibility="gone"
style="?attr/borderlessButtonStyle"
android:textAppearance="?attr/textAppearanceButton"
- android:textColor="@color/material_deep_teal_500"
+ android:textColor="?attr/colorAccent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d15b175..6161494 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -539,9 +539,12 @@
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">false</bool>
- <!-- Fast brightness animation ramp rate -->
+ <!-- Fast brightness animation ramp rate in brightness units per second-->
<integer translatable="false" name="config_brightness_ramp_rate_fast">200</integer>
+ <!-- Slow brightness animation ramp rate in brightness units per second-->
+ <integer translatable="false" name="config_brightness_ramp_rate_slow">40</integer>
+
<!-- Don't name config resources like this. It should look like config_annoyDianne -->
<bool name="config_annoy_dianne">true</bool>
@@ -2088,9 +2091,11 @@
"bugreport" = Take bug report, if available
"silent" = silent mode
"users" = list of users
+ "restart" = restart device
-->
<string-array translatable="false" name="config_globalActionsList">
<item>power</item>
+ <item>restart</item>
<item>bugreport</item>
<item>users</item>
</string-array>
@@ -2517,6 +2522,10 @@
<!-- Flag indicating whether round icons should be parsed from the application manifest. -->
<bool name="config_useRoundIcon">false</bool>
+ <!-- Flag indicating whether the assist disclosure can be disabled using
+ ASSIST_DISCLOSURE_ENABLED. -->
+ <bool name="config_allowDisablingAssistDisclosure">false</bool>
+
<!-- True if the device supports system navigation keys. -->
<bool name="config_supportSystemNavigationKeys">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5a9099b..c4594e5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -484,6 +484,10 @@
<!-- label for item that turns off power in phone options dialog -->
<string name="global_action_power_off">Power off</string>
+ <!-- label for item that restarts phone in phone options dialog -->
+ <!-- TODO: promote to separate string-->
+ <string name="global_action_restart" translatable="false">@string/sim_restart_button</string>
+
<!-- label for item that generates a bug report in the phone options dialog -->
<string name="global_action_bug_report">Bug report</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 384e9850..3c2b55b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1593,6 +1593,7 @@
<java-symbol type="string" name="bugreport_title" />
<java-symbol type="string" name="faceunlock_multiple_failures" />
<java-symbol type="string" name="global_action_power_off" />
+ <java-symbol type="string" name="global_action_restart" />
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
<java-symbol type="string" name="global_actions_airplane_mode_on_status" />
<java-symbol type="string" name="global_actions_toggle_airplane_mode" />
@@ -1760,6 +1761,7 @@
<java-symbol type="integer" name="config_undockedHdmiRotation" />
<java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
<java-symbol type="integer" name="config_brightness_ramp_rate_fast" />
+ <java-symbol type="integer" name="config_brightness_ramp_rate_slow" />
<java-symbol type="layout" name="am_compat_mode_dialog" />
<java-symbol type="layout" name="launch_warning" />
<java-symbol type="layout" name="safe_mode" />
@@ -2682,6 +2684,7 @@
<java-symbol type="drawable" name="ic_doc_generic" />
<java-symbol type="bool" name="config_nightDisplayAvailable" />
+ <java-symbol type="bool" name="config_allowDisablingAssistDisclosure" />
<java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
<java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" />
<java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" />
@@ -2691,4 +2694,7 @@
<java-symbol type="bool" name="config_permissionReviewRequired" />
+
+ <java-symbol type="drawable" name="ic_restart" />
+
</resources>
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 5221499..3ccbf17 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -29,6 +29,7 @@
* TextViewTest tests {@link TextView}.
*/
public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+ private TextView mTextView;
public TextViewTest() {
super(TextViewActivity.class);
@@ -37,16 +38,22 @@
@SmallTest
@Presubmit
public void testArray() throws Exception {
- TextView tv = new TextView(getActivity());
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextView = new TextView(getActivity());
+ }
+ });
+ getInstrumentation().waitForIdleSync();
char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
'W', 'o', 'r', 'l', 'd', '!' };
- tv.setText(c, 1, 4);
- CharSequence oldText = tv.getText();
+ mTextView.setText(c, 1, 4);
+ CharSequence oldText = mTextView.getText();
- tv.setText(c, 4, 5);
- CharSequence newText = tv.getText();
+ mTextView.setText(c, 4, 5);
+ CharSequence newText = mTextView.getText();
assertTrue(newText == oldText);
@@ -67,12 +74,18 @@
@SmallTest
public void testProcessTextActivityResultNonEditable() {
- final TextView tv = new TextView(getActivity());
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextView = new TextView(getActivity());
+ }
+ });
+ getInstrumentation().waitForIdleSync();
CharSequence originalText = "This is some text.";
- tv.setText(originalText, TextView.BufferType.SPANNABLE);
- assertEquals(originalText, tv.getText().toString());
- tv.setTextIsSelectable(true);
- Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length());
+ mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+ assertEquals(originalText, mTextView.getText().toString());
+ mTextView.setTextIsSelectable(true);
+ Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.getText().length());
// We need to run this in the UI thread, as it will create a Toast.
getActivity().runOnUiThread(new Runnable() {
@@ -81,60 +94,79 @@
CharSequence newText = "Text is replaced.";
Intent data = new Intent();
data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
- tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+ mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
}
});
getInstrumentation().waitForIdleSync();
// This is a TextView, which can't be modified. Hence no change should have been made.
- assertEquals(originalText, tv.getText().toString());
+ assertEquals(originalText, mTextView.getText().toString());
}
@SmallTest
public void testProcessTextActivityResultEditable() {
- EditText tv = new EditText(getActivity());
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextView = new EditText(getActivity());
+ }
+ });
+ getInstrumentation().waitForIdleSync();
CharSequence originalText = "This is some text.";
- tv.setText(originalText, TextView.BufferType.SPANNABLE);
- assertEquals(originalText, tv.getText().toString());
- tv.setTextIsSelectable(true);
- Selection.setSelection(tv.getText(), 0, tv.getText().length());
+ mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+ assertEquals(originalText, mTextView.getText().toString());
+ mTextView.setTextIsSelectable(true);
+ Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
CharSequence newText = "Text is replaced.";
Intent data = new Intent();
data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
- tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+ mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
- assertEquals(newText, tv.getText().toString());
+ assertEquals(newText, mTextView.getText().toString());
}
@SmallTest
public void testProcessTextActivityResultCancel() {
- EditText tv = new EditText(getActivity());
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextView = new EditText(getActivity());
+ }
+ });
+ getInstrumentation().waitForIdleSync();
CharSequence originalText = "This is some text.";
- tv.setText(originalText, TextView.BufferType.SPANNABLE);
- assertEquals(originalText, tv.getText().toString());
- tv.setTextIsSelectable(true);
- Selection.setSelection(tv.getText(), 0, tv.getText().length());
+ mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+ assertEquals(originalText, mTextView.getText().toString());
+ mTextView.setTextIsSelectable(true);
+ Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
CharSequence newText = "Text is replaced.";
Intent data = new Intent();
data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
- tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data);
+ mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED,
+ data);
- assertEquals(originalText, tv.getText().toString());
+ assertEquals(originalText, mTextView.getText().toString());
}
@SmallTest
public void testProcessTextActivityNoData() {
- EditText tv = new EditText(getActivity());
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextView = new EditText(getActivity());
+ }
+ });
+ getInstrumentation().waitForIdleSync();
CharSequence originalText = "This is some text.";
- tv.setText(originalText, TextView.BufferType.SPANNABLE);
- assertEquals(originalText, tv.getText().toString());
- tv.setTextIsSelectable(true);
- Selection.setSelection(tv.getText(), 0, tv.getText().length());
+ mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+ assertEquals(originalText, mTextView.getText().toString());
+ mTextView.setTextIsSelectable(true);
+ Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
- tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null);
+ mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null);
- assertEquals(originalText, tv.getText().toString());
+ assertEquals(originalText, mTextView.getText().toString());
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
index ce6879d..b4afdda 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
@@ -178,19 +178,40 @@
clocks.elapsedRealtime() * 1000);
offBatterySummaryParcel.setDataPosition(0);
- // Read the on battery summary from the parcel.
- BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer(
- clocks, timeBase);
- unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel);
+ // Set the timebase running again. That way any issues with tracking reported values
+ // get tested when we unparcel the timers below.
+ timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime());
- assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED));
- assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+ // Read the on battery summary from the parcel.
+ BatteryStatsImpl.SamplingTimer unparceledOnBatteryTimer =
+ new BatteryStatsImpl.SamplingTimer(clocks, timeBase);
+ unparceledOnBatteryTimer.readSummaryFromParcelLocked(onBatterySummaryParcel);
+
+ assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0,
+ BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
// Read the off battery summary from the parcel.
- unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase);
- unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel);
+ BatteryStatsImpl.SamplingTimer unparceledOffBatteryTimer =
+ new BatteryStatsImpl.SamplingTimer(clocks, timeBase);
+ unparceledOffBatteryTimer.readSummaryFromParcelLocked(offBatterySummaryParcel);
- assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED));
- assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0,
+ BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(1, unparceledOffBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+ // Now, just like with a fresh timer, the first update should be absorbed to account for
+ // data being collected when we weren't recording.
+ unparceledOnBatteryTimer.update(10, 10);
+
+ assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0,
+ BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+ unparceledOffBatteryTimer.update(10, 10);
+
+ assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0,
+ BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(1, unparceledOffBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
}
}
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index fe68654..13880ec 100755
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -16,6 +16,13 @@
</ol>
</li>
<li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li>
+ <li><a href="#reduction-in-depth">Reduction Kernels in Depth</a>
+ <ol>
+ <li><a href="#writing-reduction-kernel">Writing a reduction kernel</a></li>
+ <li><a href="#calling-reduction-kernel">Calling a reduction kernel from Java code</a></li>
+ <li><a href="#more-example">More example reduction kernels</a></li>
+ </ol>
+ </li>
</ol>
<h2>Related Samples</h2>
@@ -29,16 +36,18 @@
<p>RenderScript is a framework for running computationally intensive tasks at high performance on
Android. RenderScript is primarily oriented for use with data-parallel computation, although serial
-computationally intensive workloads can benefit as well. The RenderScript runtime will parallelize
-work across all processors available on a device, such as multi-core CPUs, GPUs, or DSPs, allowing
-you to focus on expressing algorithms rather than scheduling work or load balancing. RenderScript is
+workloads can benefit as well. The RenderScript runtime parallelizes
+work across processors available on a device, such as multi-core CPUs and GPUs. This allows
+you to focus on expressing algorithms rather than scheduling work. RenderScript is
especially useful for applications performing image processing, computational photography, or
computer vision.</p>
<p>To begin with RenderScript, there are two main concepts you should understand:</p>
<ul>
-<li>High-performance compute kernels are written in a C99-derived language.</li>
+<li>High-performance compute kernels are written in a C99-derived language. A <i>compute
+ kernel</i> is a function or collection of functions that you can direct the RenderScript runtime
+ to execute in parallel across a collection of data.</li>
<li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel
execution.</li>
@@ -48,7 +57,7 @@
<p>A RenderScript kernel typically resides in a <code>.rs</code> file in the
<code><project_root>/src/</code> directory; each <code>.rs</code> file is called a
-script. Every script contains its own set of kernels, functions, and variables. A script can
+<i>script</i>. Every script contains its own set of kernels, functions, and variables. A script can
contain:</p>
<ul>
@@ -57,23 +66,32 @@
<li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
declares the package name of the Java classes reflected from this script.
-Note that your .rs file must be part of your application package, and not in a
+Note that your <code>.rs</code> file must be part of your application package, and not in a
library project.</li>
-<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
+<li>Zero or more <strong><i>invokable functions</i></strong>. An invokable function is a single-threaded RenderScript
function that you can call from your Java code with arbitrary arguments. These are often useful for
initial setup or serial computations within a larger processing pipeline.</li>
-<li>Some number of script globals. A script global is equivalent to a global variable in C. You can
+<li><p>Zero or more <strong><i>script globals</i></strong>. A script global is equivalent to a global variable in C. You can
access script globals from Java code, and these are often used for parameter passing to RenderScript
-kernels.</li>
+kernels.</p></li>
-<li>Some number of compute kernels. A kernel is a parallel function that executes across every
-{@link android.renderscript.Element} within an {@link android.renderscript.Allocation}.
+<li><p>Zero or more <strong><i>compute kernels</i></strong>. There are two kinds of compute
+kernels: <i>mapping</i> kernels (also called <i>foreach</i> kernels)
+and <i>reduction</i> kernels.</p>
-<p>A simple kernel may look like the following:</p>
+<p>A <em>mapping kernel</em> is a parallel function that operates on a collection of {@link
+ android.renderscript.Allocation Allocations} of the same dimensions. By default, it executes
+ once for every coordinate in those dimensions. It is typically (but not exclusively) used to
+ transform a collection of input {@link android.renderscript.Allocation Allocations} to an
+ output {@link android.renderscript.Allocation} one {@link android.renderscript.Element} at a
+ time.</p>
-<pre>uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
+<ul>
+<li><p>Here is an example of a simple <strong>mapping kernel</strong>:</p>
+
+<pre>uchar4 RS_KERNEL invert(uchar4 in, uint32_t x, uint32_t y) {
uchar4 out = in;
out.r = 255 - in.r;
out.g = 255 - in.g;
@@ -81,40 +99,113 @@
return out;
}</pre>
-<p>In most respects, this is identical to a standard C function. The first notable feature is the
-<code>__attribute__((kernel))</code> applied to the function prototype. This denotes that the
-function is a RenderScript kernel instead of an invokable function. The next feature is the
-<code>in</code> argument and its type. In a RenderScript kernel, this is a special argument that is
-automatically filled in based on the input {@link android.renderscript.Allocation} passed to the
-kernel launch. By default, the kernel is run across an entire {@link
-android.renderscript.Allocation}, with one execution of the kernel body per {@link
-android.renderscript.Element} in the {@link android.renderscript.Allocation}. The third notable
-feature is the return type of the kernel. The value returned from the kernel is automatically
-written to the appropriate location in the output {@link android.renderscript.Allocation}. The
-RenderScript runtime checks to ensure that the {@link android.renderscript.Element} types of the
-input and output Allocations match the kernel's prototype; if they do not match, an exception is
-thrown.</p>
+<p>In most respects, this is identical to a standard C
+ function. The <a href="#RS_KERNEL"><code>RS_KERNEL</code></a> property applied to the
+ function prototype specifies that the function is a RenderScript mapping kernel instead of an
+ invokable function. The <code>in</code> argument is automatically filled in based on the
+ input {@link android.renderscript.Allocation} passed to the kernel launch. The
+ arguments <code>x</code> and <code>y</code> are
+ discussed <a href="#special-arguments">below</a>. The value returned from the kernel is
+ automatically written to the appropriate location in the output {@link
+ android.renderscript.Allocation}. By default, this kernel is run across its entire input
+ {@link android.renderscript.Allocation}, with one execution of the kernel function per {@link
+ android.renderscript.Element} in the {@link android.renderscript.Allocation}.</p>
-<p>A kernel may have an input {@link android.renderscript.Allocation}, an output {@link
-android.renderscript.Allocation}, or both. A kernel may not have more than one input or one output
-{@link android.renderscript.Allocation}. If more than one input or output is required, those objects
-should be bound to <code>rs_allocation</code> script globals and accessed from a kernel or invokable
-function via <code>rsGetElementAt_<em>type</em>()</code> or
-<code>rsSetElementAt_<em>type</em>()</code>.</p>
+<p>A mapping kernel may have one or more input {@link android.renderscript.Allocation
+ Allocations}, a single output {@link android.renderscript.Allocation}, or both. The
+ RenderScript runtime checks to ensure that all input and output Allocations have the same
+ dimensions, and that the {@link android.renderscript.Element} types of the input and output
+ Allocations match the kernel's prototype; if either of these checks fails, RenderScript
+ throws an exception.</p>
-<p>A kernel may access the coordinates of the current execution using the <code>x</code>,
-<code>y</code>, and <code>z</code> arguments. These arguments are optional, but the type of the
-coordinate arguments must be <code>uint32_t</code>.</p></li>
+<p class="note"><strong>NOTE:</strong> Before Android 6.0 (API level 23), a mapping kernel may
+ not have more than one input {@link android.renderscript.Allocation}.</p>
+
+<p>If you need more input or output {@link android.renderscript.Allocation Allocations} than
+ the kernel has, those objects should be bound to <code>rs_allocation</code> script globals
+ and accessed from a kernel or invokable function
+ via <code>rsGetElementAt_<i>type</i>()</code> or <code>rsSetElementAt_<i>type</i>()</code>.</p>
+
+<p><strong>NOTE:</strong> <a id="RS_KERNEL"><code>RS_KERNEL</code></a> is a macro
+ defined automatically by RenderScript for your convenience:</p>
+<pre>
+#define RS_KERNEL __attribute__((kernel))
+</pre>
+</li>
+</ul>
+
+<p>A <em>reduction kernel</em> is a family of functions that operates on a collection of input
+ {@link android.renderscript.Allocation Allocations} of the same dimensions. By default,
+ its <a href="#accumulator-function">accumulator function</a> executes once for every
+ coordinate in those dimensions. It is typically (but not exclusively) used to "reduce" a
+ collection of input {@link android.renderscript.Allocation Allocations} to a single
+ value.</p>
+
+<ul>
+<li><p>Here is an <a id="example-addint">example</a> of a simple <strong>reduction
+kernel</strong> that adds up the {@link android.renderscript.Element Elements} of its
+input:</p>
+
+<pre>#pragma rs reduce(addint) accumulator(addintAccum)
+
+static void addintAccum(int *accum, int val) {
+ *accum += val;
+}</pre>
+
+<p>A reduction kernel consists of one or more user-written functions.
+<code>#pragma rs reduce</code> is used to define the kernel by specifying its name
+(<code>addint</code>, in this example) and the names and roles of the functions that make
+up the kernel (an <code>accumulator</code> function <code>addintAccum</code>, in this
+example). All such functions must be <code>static</code>. A reduction kernel always
+requires an <code>accumulator</code> function; it may also have other functions, depending
+on what you want the kernel to do.</p>
+
+<p>A reduction kernel accumulator function must return <code>void</code> and must have at least
+two arguments. The first argument (<code>accum</code>, in this example) is a pointer to
+an <i>accumulator data item</i> and the second (<code>val</code>, in this example) is
+automatically filled in based on the input {@link android.renderscript.Allocation} passed to
+the kernel launch. The accumulator data item is created by the RenderScript runtime; by
+default, it is initialized to zero. By default, this kernel is run across its entire input
+{@link android.renderscript.Allocation}, with one execution of the accumulator function per
+{@link android.renderscript.Element} in the {@link android.renderscript.Allocation}. By
+default, the final value of the accumulator data item is treated as the result of the
+reduction, and is returned to Java. The RenderScript runtime checks to ensure that the {@link
+android.renderscript.Element} type of the input Allocation matches the accumulator function's
+prototype; if it does not match, RenderScript throws an exception.</p>
+
+<p>A reduction kernel has one or more input {@link android.renderscript.Allocation
+Allocations} but no output {@link android.renderscript.Allocation Allocations}.</p></li>
+
+<p>Reduction kernels are explained in more detail <a href="#reduction-in-depth">here</a>.</p>
+
+<p>Reduction kernels are supported in Android 7.0 (API level 24) and later.</p>
+</li>
+</ul>
+
+<p>A mapping kernel function or a reduction kernel accumulator function may access the coordinates
+of the current execution using the <a id="special-arguments">special arguments</a> <code>x</code>,
+<code>y</code>, and <code>z</code>, which must be of type <code>int</code> or <code>uint32_t</code>.
+These arguments are optional.</p>
+
+<p>A mapping kernel function or a reduction kernel accumulator
+function may also take the optional special argument
+<code>context</code> of type <a
+href='reference/rs_for_each.html#android_rs:rs_kernel_context'>rs_kernel_context</a>.
+It is needed by a family of runtime APIs that are used to query
+certain properties of the current execution -- for example, <a
+href='reference/rs_for_each.html#android_rs:rsGetDimX'>rsGetDimX</a>.
+(The <code>context</code> argument is available in Android 6.0 (API level 23) and later.)</p>
+</li>
<li>An optional <code>init()</code> function. An <code>init()</code> function is a special type of
-invokable function that is run when the script is first instantiated. This allows for some
+invokable function that RenderScript runs when the script is first instantiated. This allows for some
computation to occur automatically at script creation.</li>
-<li>Some number of static script globals and functions. A static script global is equivalent to a
-script global except that it cannot be set from Java code. A static function is a standard C
+<li>Zero or more <strong><i>static script globals and functions</i></strong>. A static script global is equivalent to a
+script global except that it cannot be accessed from Java code. A static function is a standard C
function that can be called from any kernel or invokable function in the script but is not exposed
to the Java API. If a script global or function does not need to be called from Java code, it is
-highly recommended that those be declared <code>static</code>.</li> </ul>
+highly recommended that it be declared <code>static</code>.</li> </ul>
<h4>Setting floating point precision</h4>
@@ -129,13 +220,13 @@
</li>
- <li><code>#pragma rs_fp_relaxed</code> - For apps that don’t require strict IEEE 754-2008
+ <li><code>#pragma rs_fp_relaxed</code>: For apps that don’t require strict IEEE 754-2008
compliance and can tolerate less precision. This mode enables flush-to-zero for denorms and
round-towards-zero.
</li>
- <li><code>#pragma rs_fp_imprecise</code> - For apps that don’t have stringent precision
+ <li><code>#pragma rs_fp_imprecise</code>: For apps that don’t have stringent precision
requirements. This mode enables everything in <code>rs_fp_relaxed</code> along with the
following:
@@ -162,14 +253,21 @@
available on devices running Android 3.0 (API level 11) and higher. </li>
<li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are
available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support
- Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and
+ Library</a>, which allows you to use them on devices running Android 2.3 (API level 9) and
higher.</li>
</ul>
-<p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
- provide a wider range of device compatibility. Developers targeting specific versions of
- Android can use {@link android.renderscript} if necessary.</p>
+<p>Here are the tradeoffs:</p>
+<ul>
+<li>If you use the Support Library APIs, the RenderScript portion of your application will be
+ compatible with devices running Android 2.3 (API level 9) and higher, regardless of which RenderScript
+ features you use. This allows your application to work on more devices than if you use the
+ native (<strong>{@link android.renderscript}</strong>) APIs.</li>
+<li>Certain RenderScript features are not available through the Support Library APIs.</li>
+<li>If you use the Support Library APIs, you will get (possibly significantly) larger APKs than
+if you use the native (<strong>{@link android.renderscript}</strong>) APIs.</li>
+</ul>
<h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
@@ -202,7 +300,7 @@
buildToolsVersion "23.0.3"
defaultConfig {
- minSdkVersion 8
+ minSdkVersion 9
targetSdkVersion 19
<strong>
renderscriptTargetApi 18
@@ -250,7 +348,7 @@
<p>Using RenderScript from Java code relies on the API classes located in the
{@link android.renderscript} or the {@link android.support.v8.renderscript} package. Most
-applications follow the same basic usage patterns:</p>
+applications follow the same basic usage pattern:</p>
<ol>
@@ -266,12 +364,12 @@
script.</strong> An {@link android.renderscript.Allocation} is a RenderScript object that provides
storage for a fixed amount of data. Kernels in scripts take {@link android.renderscript.Allocation}
objects as their input and output, and {@link android.renderscript.Allocation} objects can be
-accessed in kernels using <code>rsGetElementAt_<em>type</em>()</code> and
-<code>rsSetElementAt_<em>type</em>()</code> when bound as script globals. {@link
+accessed in kernels using <code>rsGetElementAt_<i>type</i>()</code> and
+<code>rsSetElementAt_<i>type</i>()</code> when bound as script globals. {@link
android.renderscript.Allocation} objects allow arrays to be passed from Java code to RenderScript
code and vice-versa. {@link android.renderscript.Allocation} objects are typically created using
-{@link android.renderscript.Allocation#createTyped} or {@link
-android.renderscript.Allocation#createFromBitmap}.</li>
+{@link android.renderscript.Allocation#createTyped createTyped()} or {@link
+android.renderscript.Allocation#createFromBitmap createFromBitmap()}.</li>
<li><strong>Create whatever scripts are necessary.</strong> There are two types of scripts available
to you when using RenderScript:
@@ -281,9 +379,9 @@
<li><strong>ScriptC</strong>: These are the user-defined scripts as described in <a
href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> above. Every script has a Java class
reflected by the RenderScript compiler in order to make it easy to access the script from Java code;
-this class will have the name <code>ScriptC_<em>filename</em></code>. For example, if the kernel
-above was located in <code>invert.rs</code> and a RenderScript context was already located in
-<code>mRS</code>, the Java code to instantiate the script would be:
+this class has the name <code>ScriptC_<i>filename</i></code>. For example, if the mapping kernel
+above were located in <code>invert.rs</code> and a RenderScript context were already located in
+<code>mRenderScript</code>, the Java code to instantiate the script would be:
<pre>ScriptC_invert invert = new ScriptC_invert(mRenderScript);</pre></li>
@@ -294,35 +392,926 @@
</ul></li>
<li><strong>Populate Allocations with data.</strong> Except for Allocations created with {@link
-android.renderscript.Allocation#createFromBitmap}, an Allocation will be populated with empty data when it is
-first created. To populate an Allocation, use one of the <code>copy</code> methods in {@link
-android.renderscript.Allocation}.</li>
+android.renderscript.Allocation#createFromBitmap createFromBitmap()}, an Allocation is populated with empty data when it is
+first created. To populate an Allocation, use one of the "copy" methods in {@link
+android.renderscript.Allocation}. The "copy" methods are <a href="#asynchronous-model">synchronous</a>.</li>
-<li><strong>Set any necessary script globals.</strong> Globals may be set using methods in the same
-<code>ScriptC_<em>filename</em></code> class with methods named
-<code>set_<em>globalname</em></code>. For example, in order to set an <code>int</code> named
-<code>elements</code>, use the Java method <code>set_elements(int)</code>. RenderScript objects can
-also be set in kernels; for example, the <code>rs_allocation</code> variable named
-<code>lookup</code> can be set with the method <code>set_lookup(Allocation)</code>.</li>
+<li><strong>Set any necessary script globals.</strong> You may set globals using methods in the
+ same <code>ScriptC_<i>filename</i></code> class named <code>set_<i>globalname</i></code>. For
+ example, in order to set an <code>int</code> variable named <code>threshold</code>, use the
+ Java method <code>set_threshold(int)</code>; and in order to set
+ an <code>rs_allocation</code> variable named <code>lookup</code>, use the Java
+ method <code>set_lookup(Allocation)</code>. The <code>set</code> methods
+ are <a href="#asynchronous-model">asynchronous</a>.</li>
-<li><strong>Launch the appropriate kernels.</strong> Methods to launch a given kernel will be
-reflected in the same <code>ScriptC_<em>filename</em></code> class with methods named
-<code>forEach_<em>kernelname</em>()</code>. These launches are asynchronous, and launches will be
-serialized in the order in which they are launched. Depending on the arguments to the kernel, the
-method will take either one or two Allocations. By default, a kernel will execute over the entire
-input or output Allocation; to execute over a subset of that Allocation, pass an appropriate {@link
-android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> method.
+<li><strong>Launch the appropriate kernels and invokable functions.</strong>
+<p>Methods to launch a given kernel are
+reflected in the same <code>ScriptC_<i>filename</i></code> class with methods named
+<code>forEach_<i>mappingKernelName</i>()</code>
+or <code>reduce_<i>reductionKernelName</i>()</code>.
+These launches are <a href="#asynchronous-model">asynchronous</a>.
+Depending on the arguments to the kernel, the
+method takes one or more Allocations, all of which must have the same dimensions. By default, a
+kernel executes over every coordinate in those dimensions; to execute a kernel over a subset of those coordinates,
+pass an appropriate {@link
+android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> or <code>reduce</code> method.</p>
-<p>Invoked functions can be launched using the <code>invoke_<em>functionname</em></code> methods
-reflected in the same <code>ScriptC_<em>filename</em></code> class.</p></li>
+<p>Launch invokable functions using the <code>invoke_<i>functionName</i></code> methods
+reflected in the same <code>ScriptC_<i>filename</i></code> class.
+These launches are <a href="#asynchronous-model">asynchronous</a>.</p></li>
-<li><strong>Copy data out of {@link android.renderscript.Allocation} objects.</strong> In order to
-access data from an {@link android.renderscript.Allocation} from Java code, that data must be copied
-back to Java buffers using one of the <code>copy</code> methods in {@link
-android.renderscript.Allocation}. These functions will synchronize with asynchronous kernel and
-function launches as necessary.</li>
+<li><strong>Retrieve data from {@link android.renderscript.Allocation} objects
+and <i><a href="#javaFutureType">javaFutureType</a></i> objects.</strong>
+In order to
+access data from an {@link android.renderscript.Allocation} from Java code, you must copy that data
+back to Java using one of the "copy" methods in {@link
+android.renderscript.Allocation}.
+In order to obtain the result of a reduction kernel, you must use the <code><i>javaFutureType</i>.get()</code> method.
+The "copy" and <code>get()</code> methods are <a href="#asynchronous-model">synchronous</a>.</li>
-<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
+<li><strong>Tear down the RenderScript context.</strong> You can destroy the RenderScript context
with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
-object to be garbage collected. This will cause any further use of any object belonging to that
+object to be garbage collected. This causes any further use of any object belonging to that
context to throw an exception.</li> </ol>
+
+<h3 id="asynchronous-model">Asynchronous execution model</h3>
+
+<p>The reflected <code>forEach</code>, <code>invoke</code>, <code>reduce</code>,
+ and <code>set</code> methods are asynchronous -- each may return to Java before completing the
+ requested action. However, the individual actions are serialized in the order in which they are launched.</p>
+
+<p>The {@link android.renderscript.Allocation} class provides "copy" methods to copy data to
+ and from Allocations. A "copy" method is synchronous, and is serialized with respect to any
+ of the asynchronous actions above that touch the same Allocation.</p>
+
+<p>The reflected <i><a href="#javaFutureType">javaFutureType</a></i> classes provide
+ a <code>get()</code> method to obtain the result of a reduction. <code>get()</code> is
+ synchronous, and is serialized with respect to the reduction (which is asynchronous).</p>
+
+<h2 id="reduction-in-depth">Reduction Kernels in Depth</h2>
+
+<p><i>Reduction</i> is the process of combining a collection of data into a single
+value. This is a useful primitive in parallel programming, with applications such as the
+following:</p>
+<ul>
+ <li>computing the sum or product over all the data</li>
+ <li>computing logical operations (<code>and</code>, <code>or</code>, <code>xor</code>)
+ over all the data</li>
+ <li>finding the minimum or maximum value within the data</li>
+ <li>searching for a specific value or for the coordinate of a specific value within the data</li>
+</ul>
+
+<p>In Android 7.0 (API level 24) and later, RenderScript supports <i>reduction kernels</i> to allow
+efficient user-written reduction algorithms. You may launch reduction kernels on inputs with
+1, 2, or 3 dimensions.<p>
+
+<p>An example above shows a simple <a href="#example-addint">addint</a> reduction kernel.
+Here is a more complicated <a id="example-findMinAndMax">findMinAndMax</a> reduction kernel
+that finds the locations of the minimum and maximum <code>long</code> values in a
+1-dimensional {@link android.renderscript.Allocation}:</p>
+
+<pre>
+#define LONG_MAX (long)((1UL << 63) - 1)
+#define LONG_MIN (long)(1UL << 63)
+
+#pragma rs reduce(findMinAndMax) \
+ initializer(fMMInit) accumulator(fMMAccumulator) \
+ combiner(fMMCombiner) outconverter(fMMOutConverter)
+
+// Either a value and the location where it was found, or <a href="#INITVAL">INITVAL</a>.
+typedef struct {
+ long val;
+ int idx; // -1 indicates <a href="#INITVAL">INITVAL</a>
+} IndexedVal;
+
+typedef struct {
+ IndexedVal min, max;
+} MinAndMax;
+
+// In discussion below, this initial value { { LONG_MAX, -1 }, { LONG_MIN, -1 } }
+// is called <a id="INITVAL">INITVAL</a>.
+static void fMMInit(MinAndMax *accum) {
+ accum->min.val = LONG_MAX;
+ accum->min.idx = -1;
+ accum->max.val = LONG_MIN;
+ accum->max.idx = -1;
+}
+
+//----------------------------------------------------------------------
+// In describing the behavior of the accumulator and combiner functions,
+// it is helpful to describe hypothetical functions
+// IndexedVal min(IndexedVal a, IndexedVal b)
+// IndexedVal max(IndexedVal a, IndexedVal b)
+// MinAndMax minmax(MinAndMax a, MinAndMax b)
+// MinAndMax minmax(MinAndMax accum, IndexedVal val)
+//
+// The effect of
+// IndexedVal min(IndexedVal a, IndexedVal b)
+// is to return the IndexedVal from among the two arguments
+// whose val is lesser, except that when an IndexedVal
+// has a negative index, that IndexedVal is never less than
+// any other IndexedVal; therefore, if exactly one of the
+// two arguments has a negative index, the min is the other
+// argument. Like ordinary arithmetic min and max, this function
+// is commutative and associative; that is,
+//
+// min(A, B) == min(B, A) // commutative
+// min(A, min(B, C)) == min((A, B), C) // associative
+//
+// The effect of
+// IndexedVal max(IndexedVal a, IndexedVal b)
+// is analogous (greater . . . never greater than).
+//
+// Then there is
+//
+// MinAndMax minmax(MinAndMax a, MinAndMax b) {
+// return MinAndMax(min(a.min, b.min), max(a.max, b.max));
+// }
+//
+// Like ordinary arithmetic min and max, the above function
+// is commutative and associative; that is:
+//
+// minmax(A, B) == minmax(B, A) // commutative
+// minmax(A, minmax(B, C)) == minmax((A, B), C) // associative
+//
+// Finally define
+//
+// MinAndMax minmax(MinAndMax accum, IndexedVal val) {
+// return minmax(accum, MinAndMax(val, val));
+// }
+//----------------------------------------------------------------------
+
+// This function can be explained as doing:
+// *accum = minmax(*accum, IndexedVal(in, x))
+//
+// This function simply computes minimum and maximum values as if
+// INITVAL.min were greater than any other minimum value and
+// INITVAL.max were less than any other maximum value. Note that if
+// *accum is INITVAL, then this function sets
+// *accum = IndexedVal(in, x)
+//
+// After this function is called, both accum->min.idx and accum->max.idx
+// will have nonnegative values:
+// - x is always nonnegative, so if this function ever sets one of the
+// idx fields, it will set it to a nonnegative value
+// - if one of the idx fields is negative, then the corresponding
+// val field must be LONG_MAX or LONG_MIN, so the function will always
+// set both the val and idx fields
+static void fMMAccumulator(MinAndMax *accum, long in, int x) {
+ IndexedVal me;
+ me.val = in;
+ me.idx = x;
+
+ if (me.val <= accum->min.val)
+ accum->min = me;
+ if (me.val >= accum->max.val)
+ accum->max = me;
+}
+
+// This function can be explained as doing:
+// *accum = minmax(*accum, *val)
+//
+// This function simply computes minimum and maximum values as if
+// INITVAL.min were greater than any other minimum value and
+// INITVAL.max were less than any other maximum value. Note that if
+// one of the two accumulator data items is INITVAL, then this
+// function sets *accum to the other one.
+static void fMMCombiner(MinAndMax *accum,
+ const MinAndMax *val) {
+ if ((accum->min.idx < 0) || (val->min.val < accum->min.val))
+ accum->min = val->min;
+ if ((accum->max.idx < 0) || (val->max.val > accum->max.val))
+ accum->max = val->max;
+}
+
+static void fMMOutConverter(int2 *result,
+ const MinAndMax *val) {
+ result->x = val->min.idx;
+ result->y = val->max.idx;
+}
+</pre>
+
+<p class="note"><strong>NOTE:</strong> There are more example reduction
+ kernels <a href="#more-example">here</a>.</p>
+
+<p>In order to run a reduction kernel, the RenderScript runtime creates <em>one or more</em>
+variables called <a id="accumulator-data-items"><strong><i>accumulator data
+items</i></strong></a> to hold the state of the reduction process. The RenderScript runtime
+picks the number of accumulator data items in such a way as to maximize performance. The type
+of the accumulator data items (<i>accumType</i>) is determined by the kernel's <i>accumulator
+function</i> -- the first argument to that function is a pointer to an accumulator data
+item. By default, every accumulator data item is initialized to zero (as if
+by <code>memset</code>); however, you may write an <i>initializer function</i> to do something
+different.</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+kernel, the accumulator data items (of type <code>int</code>) are used to add up input
+values. There is no initializer function, so each accumulator data item is initialized to
+zero.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the accumulator data items
+(of type <code>MinAndMax</code>) are used to keep track of the minimum and maximum values
+found so far. There is an initializer function to set these to <code>LONG_MAX</code> and
+<code>LONG_MIN</code>, respectively; and to set the locations of these values to -1, indicating that
+the values are not actually present in the (empty) portion of the input that has been
+processed.</p>
+
+<p>RenderScript calls your accumulator function once for every coordinate in the
+input(s). Typically, your function should update the accumulator data item in some way
+according to the input.</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+kernel, the accumulator function adds the value of an input Element to the accumulator
+data item.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the accumulator function
+checks to see whether the value of an input Element is less than or equal to the minimum
+value recorded in the accumulator data item and/or greater than or equal to the maximum
+value recorded in the accumulator data item, and updates the accumulator data item
+accordingly.</p>
+
+<p>After the accumulator function has been called once for every coordinate in the input(s),
+RenderScript must <strong>combine</strong> the <a href="#accumulator-data-items">accumulator
+data items</a> together into a single accumulator data item. You may write a <i>combiner
+function</i> to do this. If the accumulator function has a single input and
+no <a href="#special-arguments">special arguments</a>, then you do not need to write a combiner
+function; RenderScript will use the accumulator function to combine the accumulator data
+items. (You may still write a combiner function if this default behavior is not what you
+want.)</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+kernel, there is no combiner function, so the accumulator function will be used. This is
+the correct behavior, because if we split a collection of values into two pieces, and we
+add up the values in those two pieces separately, adding up those two sums is the same as
+adding up the entire collection.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the combiner function
+checks to see whether the minimum value recorded in the "source" accumulator data
+item <code>*val</code> is less then the minimum value recorded in the "destination"
+accumulator data item <code>*accum</code>, and updates <code>*accum</code>
+accordingly. It does similar work for the maximum value. This updates <code>*accum</code>
+to the state it would have had if all of the input values had been accumulated into
+<code>*accum</code> rather than some into <code>*accum</code> and some into
+<code>*val</code>.</p>
+
+<p>After all of the accumulator data items have been combined, RenderScript determines
+the result of the reduction to return to Java. You may write an <i>outconverter
+function</i> to do this. You do not need to write an outconverter function if you want
+the final value of the combined accumulator data items to be the result of the reduction.</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel,
+there is no outconverter function. The final value of the combined data items is the sum of
+all Elements of the input, which is the value we want to return.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the outconverter function
+initializes an <code>int2</code> result value to hold the locations of the minimum and
+maximum values resulting from the combination of all of the accumulator data items.</p>
+
+<h3 id="writing-reduction-kernel">Writing a reduction kernel</h3>
+
+<p><code>#pragma rs reduce</code> defines a reduction kernel by
+specifying its name and the names and roles of the functions that make
+up the kernel. All such functions must be
+<code>static</code>. A reduction kernel always requires an <code>accumulator</code>
+function; you can omit some or all of the other functions, depending on what you want the
+kernel to do.</p>
+
+<pre>#pragma rs reduce(<i>kernelName</i>) \
+ initializer(<i>initializerName</i>) \
+ accumulator(<i>accumulatorName</i>) \
+ combiner(<i>combinerName</i>) \
+ outconverter(<i>outconverterName</i>)
+</pre>
+
+<p>The meaning of the items in the <code>#pragma</code> is as follows:</p>
+<ul>
+
+<li><code>reduce(<i>kernelName</i>)</code> (mandatory): Specifies that a reduction kernel is
+being defined. A reflected Java method <code>reduce_<i>kernelName</i></code> will launch the
+kernel.</li>
+
+<li><p><code>initializer(<i>initializerName</i>)</code> (optional): Specifies the name of the
+initializer function for this reduction kernel. When you launch the kernel, RenderScript calls
+this function once for each <a href="#accumulator-data-items">accumulator data item</a>. The
+function must be defined like this:</p>
+
+<pre>static void <i>initializerName</i>(<i>accumType</i> *accum) { … }</pre>
+
+<p><code>accum</code> is a pointer to an accumulator data item for this function to
+initialize.</p>
+
+<p>If you do not provide an initializer function, RenderScript initializes every accumulator
+data item to zero (as if by <code>memset</code>), behaving as if there were an initializer
+function that looks like this:</p>
+<pre>static void <i>initializerName</i>(<i>accumType</i> *accum) {
+ memset(accum, 0, sizeof(*accum));
+}</pre>
+</li>
+
+<li><p><code><a id="accumulator-function">accumulator(<i>accumulatorName</i>)</a></code>
+(mandatory): Specifies the name of the accumulator function for this
+reduction kernel. When you launch the kernel, RenderScript calls
+this function once for every coordinate in the input(s), to update an
+accumulator data item in some way according to the input(s). The function
+must be defined like this:</p>
+
+<pre>
+static void <i>accumulatorName</i>(<i>accumType</i> *accum,
+ <i>in1Type</i> in1, <i>…,</i> <i>inNType</i> in<i>N</i>
+ <i>[, specialArguments]</i>) { … }
+</pre>
+
+<p><code>accum</code> is a pointer to an accumulator data item for this function to
+modify. <code>in1</code> through <code>in<i>N</i></code> are one <em>or more</em> arguments that
+are automatically filled in based on the inputs passed to the kernel launch, one argument
+per input. The accumulator function may optionally take any of the <a
+href="#special-arguments">special arguments</a>.</p>
+
+<p>An example kernel with multiple inputs is <a href="#dot-product"><code>dotProduct</code></a>.</p>
+</li>
+
+<li><code><a id="combiner-function">combiner(<i>combinerName</i>)</a></code>
+(optional): Specifies the name of the combiner function for this
+reduction kernel. After RenderScript calls the accumulator function
+once for every coordinate in the input(s), it calls this function as many
+times as necessary to combine all accumulator data items into a single
+accumulator data item. The function must be defined like this:</p>
+
+<pre>static void <i>combinerName</i>(<i>accumType</i> *accum, const <i>accumType</i> *other) { … }</pre>
+
+<p><code>accum</code> is a pointer to a "destination" accumulator data item for this
+function to modify. <code>other</code> is a pointer to a "source" accumulator data item
+for this function to "combine" into <code>*accum</code>.</p>
+
+<p class="note"><strong>NOTE:</strong> It is possible
+ that <code>*accum</code>, <code>*other</code>, or both have been initialized but have never
+ been passed to the accumulator function; that is, one or both have never been updated
+ according to any input data. For example, in
+ the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the combiner
+ function <code>fMMCombiner</code> explicitly checks for <code>idx < 0</code> because that
+ indicates such an accumulator data item, whose value is <a href="#INITVAL">INITVAL</a>.</p>
+
+<p>If you do not provide a combiner function, RenderScript uses the accumulator function in its
+place, behaving as if there were a combiner function that looks like this:</p>
+
+<pre>static void <i>combinerName</i>(<i>accumType</i> *accum, const <i>accumType</i> *other) {
+ <i>accumulatorName</i>(accum, *other);
+}</pre>
+
+<p>A combiner function is mandatory if the kernel has more than one input, if the input data
+ type is not the same as the accumulator data type, or if the accumulator function takes one
+ or more <a href="#special-arguments">special arguments</a>.</p>
+</li>
+
+<li><p><code><a id="outconverter-function">outconverter(<i>outconverterName</i>)</a></code>
+(optional): Specifies the name of the outconverter function for this
+reduction kernel. After RenderScript combines all of the accumulator
+data items, it calls this function to determine the result of the
+reduction to return to Java. The function must be defined like
+this:</p>
+
+<pre>static void <i>outconverterName</i>(<i>resultType</i> *result, const <i>accumType</i> *accum) { … }</pre>
+
+<p><code>result</code> is a pointer to a result data item (allocated but not initialized
+by the RenderScript runtime) for this function to initialize with the result of the
+reduction. <i>resultType</i> is the type of that data item, which need not be the same
+as <i>accumType</i>. <code>accum</code> is a pointer to the final accumulator data item
+computed by the <a href="#combiner-function">combiner function</a>.</p>
+
+<p>If you do not provide an outconverter function, RenderScript copies the final accumulator
+data item to the result data item, behaving as if there were an outconverter function that
+looks like this:</p>
+
+<pre>static void <i>outconverterName</i>(<i>accumType</i> *result, const <i>accumType</i> *accum) {
+ *result = *accum;
+}</pre>
+
+<p>If you want a different result type than the accumulator data type, then the outconverter function is mandatory.</p>
+</li>
+
+</ul>
+
+<p>Note that a kernel has input types, an accumulator data item type, and a result type,
+ none of which need to be the same. For example, in
+ the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the input
+ type <code>long</code>, accumulator data item type <code>MinAndMax</code>, and result
+ type <code>int2</code> are all different.</p>
+
+<h4 id="assume">What can't you assume?</h4>
+
+<p>You must not rely on the number of accumulator data items created by RenderScript for a
+ given kernel launch. There is no guarantee that two launches of the same kernel with the
+ same input(s) will create the same number of accumulator data items.</p>
+
+<p>You must not rely on the order in which RenderScript calls the initializer, accumulator, and
+ combiner functions; it may even call some of them in parallel. There is no guarantee that
+ two launches of the same kernel with the same input will follow the same order. The only
+ guarantee is that only the initializer function will ever see an uninitialized accumulator
+ data item. For example:</p>
+<ul>
+<li>There is no guarantee that all accumulator data items will be initialized before the
+ accumulator function is called, although it will only be called on an initialized accumulator
+ data item.</li>
+<li>There is no guarantee on the order in which input Elements are passed to the accumulator
+ function.</li>
+<li>There is no guarantee that the accumulator function has been called for all input Elements
+ before the combiner function is called.</li>
+</ul>
+
+<p>One consequence of this is that the <a href="#example-findMinAndMax">findMinAndMax</a>
+ kernel is not deterministic: If the input contains more than one occurrence of the same
+ minimum or maximum value, you have no way of knowing which occurrence the kernel will
+ find.</p>
+
+<h4 id="guarantee">What must you guarantee?</h4>
+
+<p>Because the RenderScript system can choose to execute a kernel <a href="#assume">in many
+ different ways</a>, you must follow certain rules to ensure that your kernel behaves the
+ way you want. If you do not follow these rules, you may get incorrect results,
+ nondeterministic behavior, or runtime errors.</p>
+
+<p>The rules below often say that two accumulator data items must have "<a id="the-same">the
+ same value"</a>. What does this mean? That depends on what you want the kernel to do. For
+ a mathematical reduction such as <a href="#example-addint">addint</a>, it usually makes sense
+ for "the same" to mean mathematical equality. For a "pick any" search such
+ as <a href="#example-findMinAndMax">findMinAndMax</a> ("find the location of minimum and
+ maximum input values") where there might be more than one occurrence of identical input
+ values, all locations of a given input value must be considered "the same". You could write
+ a similar kernel to "find the location of <em>leftmost</em> minimum and maximum input values"
+ where (say) a minimum value at location 100 is preferred over an identical minimum value at location
+ 200; for this kernel, "the same" would mean identical <em>location</em>, not merely
+ identical <em>value</em>, and the accumulator and combiner functions would have to be
+ different than those for <a href="#example-findMinAndMax">findMinAndMax</a>.</p>
+
+<strong>The initializer function must create an <i>identity value</i>.</strong> That is,
+ if <code><i>I</i></code> and <code><i>A</i></code> are accumulator data items initialized
+ by the initializer function, and <code><i>I</i></code> has never been passed to the
+ accumulator function (but <code><i>A</i></code> may have been), then
+<ul>
+<li><code><i>combinerName</i>(&<i>A</i>, &<i>I</i>)</code> must
+ leave <code><i>A</i></code> <a href="#the-same">the same</a></li>
+<li><code><i>combinerName</i>(&<i>I</i>, &<i>A</i>)</code> must
+ leave <code><i>I</i></code> <a href="#the-same">the same</a> as <code><i>A</i></code></li>
+</ul>
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+ kernel, an accumulator data item is initialized to zero. The combiner function for this
+ kernel performs addition; zero is the identity value for addition.</p>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a>
+ kernel, an accumulator data item is initialized
+ to <a href="#INITVAL"><code>INITVAL</code></a>.
+<ul>
+<li><code>fMMCombiner(&<i>A</i>, &<i>I</i>)</code> leaves <code><i>A</i></code> the same,
+ because <code><i>I</i></code> is <code>INITVAL</code>.</li>
+<li><code>fMMCombiner(&<i>I</i>, &<i>A</i>)</code> sets <code><i>I</i></code>
+ to <code><i>A</i></code>, because <code><i>I</i></code> is <code>INITVAL</code>.</li>
+</ul>
+Therefore, <code>INITVAL</code> is indeed an identity value.
+</p></div>
+
+<p><strong>The combiner function must be <i>commutative</i>.</strong> That is,
+ if <code><i>A</i></code> and <code><i>B</i></code> are accumulator data items initialized
+ by the initializer function, and that may have been passed to the accumulator function zero
+ or more times, then <code><i>combinerName</i>(&<i>A</i>, &<i>B</i>)</code> must
+ set <code><i>A</i></code> to <a href="#the-same">the same value</a>
+ that <code><i>combinerName</i>(&<i>B</i>, &<i>A</i>)</code>
+ sets <code><i>B</i></code>.</p>
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+ kernel, the combiner function adds the two accumulator data item values; addition is
+ commutative.</p>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel,
+<pre>
+fMMCombiner(&<i>A</i>, &<i>B</i>)
+</pre>
+is the same as
+<pre>
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+</pre>
+and <code>minmax</code> is commutative, so <code>fMMCombiner</code> is also.
+</p>
+</div>
+
+<p><strong>The combiner function must be <i>associative</i>.</strong> That is,
+ if <code><i>A</i></code>, <code><i>B</i></code>, and <code><i>C</i></code> are
+ accumulator data items initialized by the initializer function, and that may have been passed
+ to the accumulator function zero or more times, then the following two code sequences must
+ set <code><i>A</i></code> to <a href="#the-same">the same value</a>:</p>
+<ul>
+<li><pre>
+<i>combinerName</i>(&<i>A</i>, &<i>B</i>);
+<i>combinerName</i>(&<i>A</i>, &<i>C</i>);
+</pre></li>
+<li><pre>
+<i>combinerName</i>(&<i>B</i>, &<i>C</i>);
+<i>combinerName</i>(&<i>A</i>, &<i>B</i>);
+</pre></li>
+</ul>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, the
+ combiner function adds the two accumulator data item values:
+<ul>
+<li><pre>
+<i>A</i> = <i>A</i> + <i>B</i>
+<i>A</i> = <i>A</i> + <i>C</i>
+// Same as
+// <i>A</i> = (<i>A</i> + <i>B</i>) + <i>C</i>
+</pre></li>
+<li><pre>
+<i>B</i> = <i>B</i> + <i>C</i>
+<i>A</i> = <i>A</i> + <i>B</i>
+// Same as
+// <i>A</i> = <i>A</i> + (<i>B</i> + <i>C</i>)
+// <i>B</i> = <i>B</i> + <i>C</i>
+</li>
+</ul>
+Addition is associative, and so the combiner function is also.
+</p>
+</div>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel,
+<pre>
+fMMCombiner(&<i>A</i>, &<i>B</i>)
+</pre>
+is the same as
+<pre>
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+</pre>
+So the two sequences are
+<ul>
+<li><pre>
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+<i>A</i> = minmax(<i>A</i>, <i>C</i>)
+// Same as
+// <i>A</i> = minmax(minmax(<i>A</i>, <i>B</i>), <i>C</i>)
+</pre></li>
+<li><pre>
+<i>B</i> = minmax(<i>B</i>, <i>C</i>)
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+// Same as
+// <i>A</i> = minmax(<i>A</i>, minmax(<i>B</i>, <i>C</i>))
+// <i>B</i> = minmax(<i>B</i>, <i>C</i>)
+</pre></li>
+<code>minmax</code> is associative, and so <code>fMMCombiner</code> is also.
+</p>
+</div>
+
+<p><strong>The accumulator function and combiner function together must obey the <i>basic
+ folding rule</i>.</strong> That is, if <code><i>A</i></code>
+ and <code><i>B</i></code> are accumulator data items, <code><i>A</i></code> has been
+ initialized by the initializer function and may have been passed to the accumulator function
+ zero or more times, <code><i>B</i></code> has not been initialized, and <i>args</i> is
+ the list of input arguments and special arguments for a particular call to the accumulator
+ function, then the following two code sequences must set <code><i>A</i></code>
+ to <a href="#the-same">the same value</a>:</p>
+<ul>
+<li><pre>
+<i>accumulatorName</i>(&<i>A</i>, <i>args</i>); // statement 1
+</pre></li>
+<li><pre>
+<i>initializerName</i>(&<i>B</i>); // statement 2
+<i>accumulatorName</i>(&<i>B</i>, <i>args</i>); // statement 3
+<i>combinerName</i>(&<i>A</i>, &<i>B</i>); // statement 4
+</pre></li>
+</ul>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, for an input value <i>V</i>:
+<ul>
+<li>Statement 1 is the same as <code>A += <i>V</i></code></li>
+<li>Statement 2 is the same as <code>B = 0</code></li>
+<li>Statement 3 is the same as <code>B += <i>V</i></code>, which is the same as <code>B = <i>V</i></code></li>
+<li>Statement 4 is the same as <code>A += B</code>, which is the same as <code>A += <i>V</i></code></li>
+</ul>
+Statements 1 and 4 set <code><i>A</i></code> to the same value, and so this kernel obeys the
+basic folding rule.
+</p>
+</div>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, for an input
+ value <i>V</i> at coordinate <i>X</i>:
+<ul>
+<li>Statement 1 is the same as <code>A = minmax(A, IndexedVal(<i>V</i>, <i>X</i>))</code></li>
+<li>Statement 2 is the same as <code>B = <a href="#INITVAL">INITVAL</a></code></li>
+<li>Statement 3 is the same as
+<pre>
+B = minmax(B, IndexedVal(<i>V</i>, <i>X</i>))
+</pre>
+which, because <i>B</i> is the initial value, is the same as
+<pre>
+B = IndexedVal(<i>V</i>, <i>X</i>)
+</pre>
+</li>
+<li>Statement 4 is the same as
+<pre>
+A = minmax(A, B)
+</pre>
+which is the same as
+<pre>
+A = minmax(A, IndexedVal(<i>V</i>, <i>X</i>))
+</pre>
+</ul>
+Statements 1 and 4 set <code><i>A</i></code> to the same value, and so this kernel obeys the
+basic folding rule.
+</p>
+</div>
+
+<h3 id="calling-reduction-kernel">Calling a reduction kernel from Java code</h3>
+
+<p>For a reduction kernel named <i>kernelName</i> defined in the
+file <code><i>filename</i>.rs</code>, there are three methods reflected in the
+class <code>ScriptC_<i>filename</i></code>:</p>
+
+<pre>
+// Method 1
+public <i>javaFutureType</i> reduce_<i>kernelName</i>(Allocation ain1, <i>…,</i>
+ Allocation ain<i>N</i>);
+
+// Method 2
+public <i>javaFutureType</i> reduce_<i>kernelName</i>(Allocation ain1, <i>…,</i>
+ Allocation ain<i>N</i>,
+ Script.LaunchOptions sc);
+
+// Method 3
+public <i>javaFutureType</i> reduce_<i>kernelName</i>(<i><a href="#devec">devecSiIn1Type</a></i>[] in1, …,
+ <i><a href="#devec">devecSiInNType</a></i>[] in<i>N</i>);
+</pre>
+
+<p>Here are some examples of calling the <a href="#example-addint">addint</a> kernel:</p>
+<pre>
+ScriptC_example script = new ScriptC_example(mRenderScript);
+
+// 1D array
+// and obtain answer immediately
+int input1[] = <i>…</i>;
+int sum1 = script.reduce_addint(input1).get(); // Method 3
+
+// 2D allocation
+// and do some additional work before obtaining answer
+Type.Builder typeBuilder =
+ new Type.Builder(RS, Element.I32(RS));
+typeBuilder.setX(<i>…</i>);
+typeBuilder.setY(<i>…</i>);
+Allocation input2 = createTyped(RS, typeBuilder.create());
+<i>populateSomehow</i>(input2); // fill in input Allocation with data
+script.result_int result2 = script.reduce_addint(input2); // Method 1
+<i>doSomeAdditionalWork</i>(); // might run at same time as reduction
+int sum2 = result2.get();
+</pre>
+
+<p><strong>Method 1</strong> has one input {@link android.renderscript.Allocation} argument for
+ every input argument in the kernel's <a href="#accumulator-function">accumulator
+ function</a>. The RenderScript runtime checks to ensure that all of the input Allocations
+ have the same dimensions and that the {@link android.renderscript.Element} type of each of
+ the input Allocations matches that of the corresponding input argument of the accumulator
+ function's prototype. If any of these checks fail, RenderScript throws an exception. The
+ kernel executes over every coordinate in those dimensions.</p>
+
+<p><strong>Method 2</strong> is the same as Method 1 except that Method 2 takes an additional
+ argument <code>sc</code> that can be used to limit the kernel execution to a subset of the
+ coordinates.</p>
+
+<p><strong><a id="reduce-method-3">Method 3</a></strong> is the same as Method 1 except that
+ instead of taking Allocation inputs it takes Java array inputs. This is a convenience that
+ saves you from having to write code to explicitly create an Allocation and copy data to it
+ from a Java array. <em>However, using Method 3 instead of Method 1 does not increase the
+ performance of the code</em>. For each input array, Method 3 creates a temporary
+ 1-dimensional Allocation with the appropriate {@link android.renderscript.Element} type and
+ {@link android.renderscript.Allocation#setAutoPadding} enabled, and copies the array to the
+ Allocation as if by the appropriate <code>copyFrom()</code> method of {@link
+ android.renderscript.Allocation}. It then calls Method 1, passing those temporary
+ Allocations.</p>
+<p class="note"><strong>NOTE:</strong> If your application will make multiple kernel calls with
+ the same array, or with different arrays of the same dimensions and Element type, you may improve
+ performance by explicitly creating, populating, and reusing Allocations yourself, instead of
+ by using Method 3.</p>
+<p><strong><i><a id="javaFutureType">javaFutureType</a></i></strong>,
+ the return type of the reflected reduction methods, is a reflected
+ static nested class within the <code>ScriptC_<i>filename</i></code>
+ class. It represents the future result of a reduction
+ kernel run. To obtain the actual result of the run, call
+ the <code>get()</code> method of that class, which returns a value
+ of type <i>javaResultType</i>. <code>get()</code> is <a href="#asynchronous-model">synchronous</a>.</p>
+
+<pre>
+public class ScriptC_<i>filename</i> extends ScriptC {
+ public static class <i>javaFutureType</i> {
+ public <i>javaResultType</i> get() { … }
+ }
+}
+</pre>
+
+<p><strong><i>javaResultType</i></strong> is determined from the <i>resultType</i> of the
+ <a href="#outconverter-function">outconverter function</a>. Unless <i>resultType</i> is an
+ unsigned type (scalar, vector, or array), <i>javaResultType</i> is the directly corresponding
+ Java type. If <i>resultType</i> is an unsigned type and there is a larger Java signed type,
+ then <i>javaResultType</i> is that larger Java signed type; otherwise, it is the directly
+ corresponding Java type. For example:</p>
+<ul>
+<li>If <i>resultType</i> is <code>int</code>, <code>int2</code>, or <code>int[15]</code>,
+ then <i>javaResultType</i> is <code>int</code>, <code>Int2</code>,
+ or <code>int[]</code>. All values of <i>resultType</i> can be represented
+ by <i>javaResultType</i>.</li>
+<li>If <i>resultType</i> is <code>uint</code>, <code>uint2</code>, or <code>uint[15]</code>,
+ then <i>javaResultType</i> is <code>long</code>, <code>Long2</code>,
+ or <code>long[]</code>. All values of <i>resultType</i> can be represented
+ by <i>javaResultType</i>.</li>
+<li>If <i>resultType</i> is <code>ulong</code>, <code>ulong2</code>,
+ or <code>ulong[15]</code>, then <i>javaResultType</i>
+ is <code>long</code>, <code>Long2</code>, or <code>long[]</code>. There are certain values
+ of <i>resultType</i> that cannot be represented by <i>javaResultType</i>.</li>
+</ul>
+
+<p><strong><i>javaFutureType</i></strong> is the future result type corresponding
+ to the <i>resultType</i> of the <a href="#outconverter-function">outconverter
+ function</a>.</p>
+<ul>
+<li>If <i>resultType</i> is not an array type, then <i>javaFutureType</i>
+ is <code>result_<i>resultType</i></code>.</li>
+<li>If <i>resultType</i> is an array of length <i>Count</i> with members of type <i>memberType</i>,
+ then <i>javaFutureType</i> is <code>resultArray<i>Count</i>_<i>memberType</i></code>.</li>
+</ul>
+
+<p>For example:</p>
+
+<pre>
+public class ScriptC_<i>filename</i> extends ScriptC {
+ // for kernels with int result
+ public static class result_int {
+ public int get() { … }
+ }
+
+ // for kernels with int[10] result
+ public static class resultArray10_int {
+ public int[] get() { … }
+ }
+
+ // for kernels with int2 result
+ // note that the Java type name "Int2" is not the same as the script type name "int2"
+ public static class result_int2 {
+ public Int2 get() { … }
+ }
+
+ // for kernels with int2[10] result
+ // note that the Java type name "Int2" is not the same as the script type name "int2"
+ public static class resultArray10_int2 {
+ public Int2[] get() { … }
+ }
+
+ // for kernels with uint result
+ // note that the Java type "long" is a wider signed type than the unsigned script type "uint"
+ public static class result_uint {
+ public long get() { … }
+ }
+
+ // for kernels with uint[10] result
+ // note that the Java type "long" is a wider signed type than the unsigned script type "uint"
+ public static class resultArray10_uint {
+ public long[] get() { … }
+ }
+
+ // for kernels with uint2 result
+ // note that the Java type "Long2" is a wider signed type than the unsigned script type "uint2"
+ public static class result_uint2 {
+ public Long2 get() { … }
+ }
+
+ // for kernels with uint2[10] result
+ // note that the Java type "Long2" is a wider signed type than the unsigned script type "uint2"
+ public static class resultArray10_uint2 {
+ public Long2[] get() { … }
+ }
+}
+</pre>
+
+<p>If <i>javaResultType</i> is an object type (including an array type), each call
+ to <code><i>javaFutureType</i>.get()</code> on the same instance will return the same
+ object.</p>
+
+<p>If <i>javaResultType</i> cannot represent all values of type <i>resultType</i>, and a
+ reduction kernel produces an unrepresentible value,
+ then <code><i>javaFutureType</i>.get()</code> throws an exception.</p>
+
+<h4 id="devec">Method 3 and <i>devecSiInXType</i></h4>
+
+<p><strong><i>devecSiInXType</i></strong> is the Java type corresponding to
+ the <i>inXType</i> of the corresponding argument of
+ the <a href="#accumulator-function">accumulator function</a>. Unless <i>inXType</i> is an
+ unsigned type or a vector type, <i>devecSiInXType</i> is the directly corresponding Java
+ type. If <i>inXType</i> is an unsigned scalar type, then <i>devecSiInXType</i> is the
+ Java type directly corresponding to the signed scalar type of the same
+ size. If <i>inXType</i> is a signed vector type, then <i>devecSiInXType</i> is the Java
+ type directly corresponding to the vector component type. If <i>inXType</i> is an unsigned
+ vector type, then <i>devecSiInXType</i> is the Java type directly corresponding to the
+ signed scalar type of the same size as the vector component type. For example:</p>
+<ul>
+<li>If <i>inXType</i> is <code>int</code>, then <i>devecSiInXType</i>
+ is <code>int</code>.</li>
+<li>If <i>inXType</i> is <code>int2</code>, then <i>devecSiInXType</i>
+ is <code>int</code>. The array is a <em>flattened</em> representation: It has twice as
+ many <em>scalar</em> Elements as the Allocation has 2-component <em>vector</em>
+ Elements. This is the same way that the <code>copyFrom()</code> methods of {@link
+ android.renderscript.Allocation} work.</li>
+<li>If <i>inXType</i> is <code>uint</code>, then <i>deviceSiInXType</i>
+ is <code>int</code>. A signed value in the Java array is interpreted as an unsigned value of
+ the same bitpattern in the Allocation. This is the same way that the <code>copyFrom()</code>
+ methods of {@link android.renderscript.Allocation} work.</li>
+<li>If <i>inXType</i> is <code>uint2</code>, then <i>deviceSiInXType</i>
+ is <code>int</code>. This is a combination of the way <code>int2</code> and <code>uint</code>
+ are handled: The array is a flattened representation, and Java array signed values are
+ interpreted as RenderScript unsigned Element values.</li>
+</ul>
+
+<p>Note that for <a href="#reduce-method-3">Method 3</a>, input types are handled differently
+than result types:</p>
+
+<ul>
+<li>A script's vector input is flattened on the Java side, whereas a script's vector result is not.</li>
+<li>A script's unsigned input is represented as a signed input of the same size on the Java
+ side, whereas a script's unsigned result is represented as a widened signed type on the Java
+ side (except in the case of <code>ulong</code>).</li>
+</ul>
+
+<h3 id="more-example">More example reduction kernels</h3>
+
+<pre id="dot-product">
+#pragma rs reduce(dotProduct) \
+ accumulator(dotProductAccum) combiner(dotProductSum)
+
+// Note: No initializer function -- therefore,
+// each accumulator data item is implicitly initialized to 0.0f.
+
+static void dotProductAccum(float *accum, float in1, float in2) {
+ *accum += in1*in2;
+}
+
+// combiner function
+static void dotProductSum(float *accum, const float *val) {
+ *accum += *val;
+}
+</pre>
+
+<pre>
+// Find a zero Element in a 2D allocation; return (-1, -1) if none
+#pragma rs reduce(fz2) \
+ initializer(fz2Init) \
+ accumulator(fz2Accum) combiner(fz2Combine)
+
+static void fz2Init(int2 *accum) { accum->x = accum->y = -1; }
+
+static void fz2Accum(int2 *accum,
+ int inVal,
+ int x /* special arg */,
+ int y /* special arg */) {
+ if (inVal==0) {
+ accum->x = x;
+ accum->y = y;
+ }
+}
+
+static void fz2Combine(int2 *accum, const int2 *accum2) {
+ if (accum2->x >= 0) *accum = *accum2;
+}
+</pre>
+
+<pre>
+// Note that this kernel returns an array to Java
+#pragma rs reduce(histogram) \
+ accumulator(hsgAccum) combiner(hsgCombine)
+
+#define BUCKETS 256
+typedef uint32_t Histogram[BUCKETS];
+
+// Note: No initializer function --
+// therefore, each bucket is implicitly initialized to 0.
+
+static void hsgAccum(Histogram *h, uchar in) { ++(*h)[in]; }
+
+static void hsgCombine(Histogram *accum,
+ const Histogram *addend) {
+ for (int i = 0; i < BUCKETS; ++i)
+ (*accum)[i] += (*addend)[i];
+}
+
+// Determines the mode (most frequently occurring value), and returns
+// the value and the frequency.
+//
+// If multiple values have the same highest frequency, returns the lowest
+// of those values.
+//
+// Shares functions with the histogram reduction kernel.
+#pragma rs reduce(mode) \
+ accumulator(hsgAccum) combiner(hsgCombine) \
+ outconverter(modeOutConvert)
+
+static void modeOutConvert(int2 *result, const Histogram *h) {
+ uint32_t mode = 0;
+ for (int i = 1; i < BUCKETS; ++i)
+ if ((*h)[i] > (*h)[mode]) mode = i;
+ result->x = mode;
+ result->y = (*h)[mode];
+}
+</pre>
diff --git a/docs/html/training/testing/unit-testing/local-unit-tests.jd b/docs/html/training/testing/unit-testing/local-unit-tests.jd
index 8b109ee..d19de4f 100644
--- a/docs/html/training/testing/unit-testing/local-unit-tests.jd
+++ b/docs/html/training/testing/unit-testing/local-unit-tests.jd
@@ -112,12 +112,16 @@
returned result against the expected result.</p>
<h3 id="mocking-dependencies">Mock Android dependencies</h3>
-<p>
-By default, the <a href="{@docRoot}tools/building/plugin-for-gradle.html">
-Android Plug-in for Gradle</a> executes your local unit tests against a modified
-version of the {@code android.jar} library, which does not contain any actual code. Instead, method
-calls to Android classes from your unit test throw an exception.
-</p>
+
+<p>By default, the <a href=
+"{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for
+Gradle</a> executes your local unit tests against a modified version of the
+{@code android.jar} library, which does not contain any actual code. Instead,
+method calls to Android classes from your unit test throw an exception. This is
+to make sure you test only your code and do not depend on any
+particular behavior of the Android platform (that you have not explicitly
+mocked).</p>
+
<p>
You can use a mocking framework to stub out external dependencies in your code, to easily test that
your component interacts with a dependency in an expected way. By substituting Android dependencies
@@ -195,6 +199,26 @@
class="external-link">sample code</a>.
</p>
+<p>If the exceptions thrown by Android APIs in the
+<code>android.jar</code> are problematic for your tests, you can change the behavior so that methods
+instead return either null or zero by adding the following configuration in your project's
+top-level <code>build.gradle</code> file:</p>
+
+<pre>
+android {
+ ...
+ testOptions {
+ unitTests.returnDefaultValues = true
+ }
+}
+</pre>
+
+<p class="caution"><strong>Caution:</strong>
+Setting the <code>returnDefaultValues</code> property to <code>true</code>
+should be done with care. The null/zero return values can introduce
+regressions in your tests, which are hard to debug and might allow failing tests
+to pass. Only use it as a last resort.</p>
+
<h2 id="run">Run Local Unit Tests</h2>
diff --git a/libs/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp
index f72ffaa..b1495ef 100644
--- a/libs/common_time/common_time_server.cpp
+++ b/libs/common_time/common_time_server.cpp
@@ -615,12 +615,11 @@
ssize_t recvBytes = recvfrom(
mSocket, buf, sizeof(buf), 0,
- reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen);
+ reinterpret_cast<sockaddr *>(&srcAddr), &srcAddrLen);
if (recvBytes < 0) {
- mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "recvfrom failed (res %d, errno %d)",
- recvBytes, errno);
+ mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG, "recvfrom failed (%s)",
+ strerror(errno));
return false;
}
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 72bac6c..aac355c 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -124,7 +124,7 @@
Finished,
};
- BaseRenderNodeAnimator(float finalValue);
+ explicit BaseRenderNodeAnimator(float finalValue);
virtual ~BaseRenderNodeAnimator();
virtual float getValue(RenderNode* target) const = 0;
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index 6afff1b..e2e70372 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -27,7 +27,7 @@
// Lifecycle
///////////////////////////////////////////////////////////////////////////////
-void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
+void AssetAtlas::init(const sp<GraphicBuffer>& buffer, int64_t* map, int count) {
if (mImage) {
return;
}
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 75400ff..b32e518 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -109,7 +109,7 @@
* initialized. To re-initialize the atlas, you must
* first call terminate().
*/
- ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
+ ANDROID_API void init(const sp<GraphicBuffer>& buffer, int64_t* map, int count);
/**
* Destroys the atlas texture. This object can be
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index a8205c8..c5d8767 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -101,7 +101,7 @@
const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
const LsaVector<FunctorContainer>& getFunctors() const { return functors; }
- const LsaVector<VectorDrawableRoot*>& getVectorDrawables() { return vectorDrawables; }
+ const LsaVector<VectorDrawableRoot*>& getVectorDrawables() const { return vectorDrawables; }
size_t addChild(NodeOpType* childOp);
diff --git a/libs/hwui/Image.h b/libs/hwui/Image.h
index 2514535..b8f5a5b 100644
--- a/libs/hwui/Image.h
+++ b/libs/hwui/Image.h
@@ -38,7 +38,7 @@
* cannot be created, getTexture() will return 0 and getImage() will
* return EGL_NO_IMAGE_KHR.
*/
- Image(sp<GraphicBuffer> buffer);
+ explicit Image(sp<GraphicBuffer> buffer);
~Image();
/**
diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h
index 66ce119..6512008 100644
--- a/libs/hwui/Interpolator.h
+++ b/libs/hwui/Interpolator.h
@@ -43,7 +43,7 @@
class ANDROID_API AccelerateInterpolator : public Interpolator {
public:
- AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {}
+ explicit AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {}
virtual float interpolate(float input) override;
private:
const float mFactor;
@@ -52,7 +52,7 @@
class ANDROID_API AnticipateInterpolator : public Interpolator {
public:
- AnticipateInterpolator(float tension) : mTension(tension) {}
+ explicit AnticipateInterpolator(float tension) : mTension(tension) {}
virtual float interpolate(float input) override;
private:
const float mTension;
@@ -60,7 +60,7 @@
class ANDROID_API AnticipateOvershootInterpolator : public Interpolator {
public:
- AnticipateOvershootInterpolator(float tension) : mTension(tension) {}
+ explicit AnticipateOvershootInterpolator(float tension) : mTension(tension) {}
virtual float interpolate(float input) override;
private:
const float mTension;
@@ -73,7 +73,7 @@
class ANDROID_API CycleInterpolator : public Interpolator {
public:
- CycleInterpolator(float cycles) : mCycles(cycles) {}
+ explicit CycleInterpolator(float cycles) : mCycles(cycles) {}
virtual float interpolate(float input) override;
private:
const float mCycles;
@@ -81,7 +81,7 @@
class ANDROID_API DecelerateInterpolator : public Interpolator {
public:
- DecelerateInterpolator(float factor) : mFactor(factor) {}
+ explicit DecelerateInterpolator(float factor) : mFactor(factor) {}
virtual float interpolate(float input) override;
private:
const float mFactor;
@@ -94,7 +94,7 @@
class ANDROID_API OvershootInterpolator : public Interpolator {
public:
- OvershootInterpolator(float tension) : mTension(tension) {}
+ explicit OvershootInterpolator(float tension) : mTension(tension) {}
virtual float interpolate(float input) override;
private:
const float mTension;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c90abad..dd20a76 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -23,6 +23,7 @@
#include "RecordedOp.h"
#include "TreeInfo.h"
#include "utils/MathUtils.h"
+#include "utils/StringUtils.h"
#include "utils/TraceUtils.h"
#include "VectorDrawable.h"
#include "renderstate/RenderState.h"
@@ -68,31 +69,36 @@
* This function is a simplified version of replay(), where we simply retrieve and log the
* display list. This function should remain in sync with the replay() function.
*/
-void RenderNode::output(uint32_t level, const char* label) {
- ALOGD("%s (%s %p%s%s%s%s%s)",
- label,
- getName(),
- this,
- (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""),
- (properties().hasShadow() ? ", casting shadow" : ""),
- (isRenderable() ? "" : ", empty"),
- (properties().getProjectBackwards() ? ", projected" : ""),
- (mLayer != nullptr ? ", on HW Layer" : ""));
- properties().debugOutputProperties(level + 1);
+void RenderNode::output() {
+ LogcatStream strout;
+ strout << "Root";
+ output(strout, 0);
+}
+
+void RenderNode::output(std::ostream& output, uint32_t level) {
+ output << " (" << getName() << " " << this
+ << (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : "")
+ << (properties().hasShadow() ? ", casting shadow" : "")
+ << (isRenderable() ? "" : ", empty")
+ << (properties().getProjectBackwards() ? ", projected" : "")
+ << (mLayer != nullptr ? ", on HW Layer" : "")
+ << ")" << std::endl;
+
+ properties().debugOutputProperties(output, level + 1);
if (mDisplayList) {
for (auto&& op : mDisplayList->getOps()) {
- std::stringstream strout;
- OpDumper::dump(*op, strout, level + 1);
+ OpDumper::dump(*op, output, level + 1);
if (op->opId == RecordedOpId::RenderNodeOp) {
auto rnOp = reinterpret_cast<const RenderNodeOp*>(op);
- rnOp->renderNode->output(level + 1, strout.str().c_str());
+ rnOp->renderNode->output(output, level + 1);
} else {
- ALOGD("%s", strout.str().c_str());
+ output << std::endl;
}
}
}
- ALOGD("%*s/RenderNode(%s %p)", level * 2, "", getName(), this);
+ output << std::string(level * 2, ' ') << "/RenderNode(" << getName() << " " << this << ")";
+ output << std::endl;
}
void RenderNode::copyTo(proto::RenderNode *pnode) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index ee045aa..a0679b1 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -102,7 +102,7 @@
void computeOrdering();
- ANDROID_API void output(uint32_t level = 0, const char* label = "Root");
+ ANDROID_API void output();
ANDROID_API int getDebugSize();
void copyTo(proto::RenderNode* node);
@@ -247,6 +247,7 @@
void incParentRefCount() { mParentCount++; }
void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);
+ void output(std::ostream& output, uint32_t level);
String8 mName;
sp<VirtualLightRefBase> mUserContext;
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 7e3cad4..b0114bc 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -99,26 +99,34 @@
return *this;
}
-void RenderProperties::debugOutputProperties(const int level) const {
+static void dumpMatrix(std::ostream& output, std::string& indent,
+ const char* label, SkMatrix* matrix) {
+ if (matrix) {
+ output << indent << "(" << label << " " << matrix << ": ";
+ output << std::fixed << std::setprecision(2);
+ output << "[" << matrix->get(0) << " "<< matrix->get(1) << " " << matrix->get(2) << "]";
+ output << " [" << matrix->get(3) << " "<< matrix->get(4) << " " << matrix->get(5) << "]";
+ output << " [" << matrix->get(6) << " "<< matrix->get(7) << " " << matrix->get(8) << "]";
+ output << ")" << std::endl;
+ }
+}
+
+void RenderProperties::debugOutputProperties(std::ostream& output, const int level) const {
+ auto indent = std::string(level * 2, ' ');
if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) {
- ALOGD("%*s(Translate (left, top) %d, %d)", level * 2, "",
- mPrimitiveFields.mLeft, mPrimitiveFields.mTop);
+ output << indent << "(Translate (left, top) " << mPrimitiveFields.mLeft
+ << ", " << mPrimitiveFields.mTop << ")" << std::endl;
}
- if (mStaticMatrix) {
- ALOGD("%*s(ConcatMatrix (static) %p: " SK_MATRIX_STRING ")",
- level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix));
- }
- if (mAnimationMatrix) {
- ALOGD("%*s(ConcatMatrix (animation) %p: " SK_MATRIX_STRING ")",
- level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix));
- }
+ dumpMatrix(output, indent, "ConcatMatrix (static)", mStaticMatrix);
+ dumpMatrix(output, indent, "ConcatMatrix (animation)", mAnimationMatrix);
+
+ output << std::fixed << std::setprecision(2);
if (hasTransformMatrix()) {
if (isTransformTranslateOnly()) {
- ALOGD("%*s(Translate %.2f, %.2f, %.2f)",
- level * 2, "", getTranslationX(), getTranslationY(), getZ());
+ output << indent << "(Translate " << getTranslationX() << ", " << getTranslationY()
+ << ", " << getZ() << ")" << std::endl;
} else {
- ALOGD("%*s(ConcatMatrix %p: " SK_MATRIX_STRING ")",
- level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix));
+ dumpMatrix(output, indent, "ConcatMatrix ", mComputedFields.mTransformMatrix);
}
}
@@ -132,7 +140,7 @@
if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) {
// simply scale rendering content's alpha
- ALOGD("%*s(ScaleAlpha %.2f)", level * 2, "", mPrimitiveFields.mAlpha);
+ output << indent << "(ScaleAlpha " << mPrimitiveFields.mAlpha << ")" << std::endl;
} else {
// savelayeralpha to create an offscreen buffer to apply alpha
Rect layerBounds(0, 0, getWidth(), getHeight());
@@ -140,35 +148,40 @@
getClippingRectForFlags(clipFlags, &layerBounds);
clipFlags = 0; // all clipping done by savelayer
}
- ALOGD("%*s(SaveLayerAlpha %d, %d, %d, %d, %d, 0x%x)", level * 2, "",
- (int)layerBounds.left, (int)layerBounds.top,
- (int)layerBounds.right, (int)layerBounds.bottom,
- (int)(mPrimitiveFields.mAlpha * 255),
- SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer);
+ output << indent << "(SaveLayerAlpha "
+ << (int)layerBounds.left << ", " << (int)layerBounds.top << ", "
+ << (int)layerBounds.right << ", " << (int)layerBounds.bottom << ", "
+ << (int)(mPrimitiveFields.mAlpha * 255) << ", 0x" << std::hex
+ << (SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer) << ")" << std::dec
+ << std::endl;
}
}
if (clipFlags) {
Rect clipRect;
getClippingRectForFlags(clipFlags, &clipRect);
- ALOGD("%*s(ClipRect %d, %d, %d, %d)", level * 2, "",
- (int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom);
+ output << indent << "(ClipRect "
+ << (int)clipRect.left << ", " << (int)clipRect.top << ", "
+ << (int)clipRect.right << ", " << (int)clipRect.bottom << ")" << std::endl;
}
if (getRevealClip().willClip()) {
Rect bounds;
getRevealClip().getBounds(&bounds);
- ALOGD("%*s(Clip to reveal clip with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
- RECT_ARGS(bounds));
+ output << indent << "(Clip to reveal clip with bounds "
+ << bounds.left << ", " << bounds.top << ", "
+ << bounds.right << ", " << bounds.bottom << ")" << std::endl;
}
auto& outline = mPrimitiveFields.mOutline;
if (outline.getShouldClip()) {
if (outline.isEmpty()) {
- ALOGD("%*s(Clip to empty outline)", level * 2, "");
+ output << indent << "(Clip to empty outline)";
} else if (outline.willClip()) {
- ALOGD("%*s(Clip to outline with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
- RECT_ARGS(outline.getBounds()));
+ const Rect& bounds = outline.getBounds();
+ output << indent << "(Clip to outline with bounds "
+ << bounds.left << ", " << bounds.top << ", "
+ << bounds.right << ", " << bounds.bottom << ")" << std::endl;
}
}
}
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 00494a1..2f5223c 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -35,6 +35,7 @@
#include <cutils/compiler.h>
#include <androidfw/ResourceTypes.h>
#include <utils/Log.h>
+#include <ostream>
class SkBitmap;
class SkColorFilter;
@@ -574,7 +575,7 @@
return mPrimitiveFields.mProjectBackwards;
}
- void debugOutputProperties(const int level) const;
+ void debugOutputProperties(std::ostream& output, const int level) const;
void updateMatrix();
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 731d9bb..9e0fb12 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -106,7 +106,7 @@
void interruptForFunctorInvoke();
void resumeFromFunctorInvoke();
- RenderState(renderthread::RenderThread& thread);
+ explicit RenderState(renderthread::RenderThread& thread);
~RenderState();
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 459baed..41047fe 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -86,7 +86,7 @@
private:
friend class RenderThread;
- EglManager(RenderThread& thread);
+ explicit EglManager(RenderThread& thread);
// EglContext is never destroyed, method is purposely not implemented
~EglManager();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index d6eea87..3edd423 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -157,7 +157,7 @@
SETUP_TASK(updateSurface);
args->context = mContext;
args->surface = surface.get();
- postAndWait(task);
+ post(task);
}
CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index fd3cf37..0d90afa 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -15,6 +15,7 @@
*/
#include <gtest/gtest.h>
+#include <VectorDrawable.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
@@ -132,3 +133,38 @@
canvasContext->destroy(nullptr);
}
+
+RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
+
+ VectorDrawable::Group* group = new VectorDrawable::Group();
+ VectorDrawableRoot* vectorDrawable = new VectorDrawableRoot(group);
+ auto rootNode = TestUtils::createNode(0, 0, 200, 400,
+ [&](RenderProperties& props, Canvas& canvas) {
+ canvas.drawVectorDrawable(vectorDrawable);
+ });
+ ContextFactory contextFactory;
+ std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+ renderThread, false, rootNode.get(), &contextFactory));
+ TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+ DamageAccumulator damageAccumulator;
+ LayerUpdateQueue layerUpdateQueue;
+ info.damageAccumulator = &damageAccumulator;
+ info.layerUpdateQueue = &layerUpdateQueue;
+ info.observer = nullptr;
+
+ // Put node on HW layer
+ rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+
+ TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
+ rootNode->prepareTree(info);
+
+ // Check that the VD is in the dislay list, and the layer update queue contains the correct
+ // damage rect.
+ EXPECT_FALSE(rootNode->getDisplayList()->getVectorDrawables().empty());
+ EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
+ EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
+ EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
+
+ delete vectorDrawable;
+ canvasContext->destroy(nullptr);
+}
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
index 0e4ffdc..c9d12bc 100644
--- a/libs/hwui/thread/TaskManager.h
+++ b/libs/hwui/thread/TaskManager.h
@@ -78,7 +78,7 @@
class WorkerThread: public Thread {
public:
- explicit WorkerThread(const String8 name): mSignal(Condition::WAKE_UP_ONE), mName(name) { }
+ explicit WorkerThread(const String8& name): mSignal(Condition::WAKE_UP_ONE), mName(name) { }
bool addTask(const TaskWrapper& task);
size_t getTaskCount() const;
diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h
index 5add957..af5d10f 100644
--- a/libs/hwui/utils/StringUtils.h
+++ b/libs/hwui/utils/StringUtils.h
@@ -16,10 +16,14 @@
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
+#include <iomanip>
+#include <iostream>
+#include <ostream>
+#include <sstream>
#include <string>
#include <unordered_set>
-#include <ostream>
-#include <iomanip>
+
+#include <utils/Log.h>
namespace android {
namespace uirenderer {
@@ -51,6 +55,22 @@
}
};
+class LogcatStream: public std::ostream {
+ class LogcatStreamBuf: public std::stringbuf {
+ virtual int sync() {
+ ALOGD("%s", str().c_str());
+ str("");
+ return 0;
+ }
+ };
+
+ LogcatStreamBuf buffer;
+public:
+ LogcatStream()
+ :std::ostream(&buffer) {
+ }
+};
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/utils/Timing.h b/libs/hwui/utils/Timing.h
index dd8847a..4b1fabe 100644
--- a/libs/hwui/utils/Timing.h
+++ b/libs/hwui/utils/Timing.h
@@ -22,7 +22,7 @@
#define TIME_METHOD() MethodTimer __method_timer(__func__)
class MethodTimer {
public:
- MethodTimer(const char* name)
+ explicit MethodTimer(const char* name)
: mMethodName(name) {
gettimeofday(&mStart, nullptr);
}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 268e442..d413083 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -25,6 +25,7 @@
import android.system.OsConstants;
import android.util.Log;
import android.util.Pair;
+import android.annotation.IntDef;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -55,6 +56,8 @@
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -69,7 +72,6 @@
public class ExifInterface {
private static final String TAG = "ExifInterface";
private static final boolean DEBUG = false;
- private static final boolean HANDLE_RAW = false;
// The Exif tag names. See Tiff 6.0 Section 3 and Section 8.
/** Type is String. */
@@ -1167,16 +1169,24 @@
// The following values are used for indicating pointers to the other Image File Directories.
// Indices of Exif Ifd tag groups
- private static final int IFD_TIFF_HINT = 0;
- private static final int IFD_EXIF_HINT = 1;
- private static final int IFD_GPS_HINT = 2;
- private static final int IFD_INTEROPERABILITY_HINT = 3;
- private static final int IFD_THUMBNAIL_HINT = 4;
- private static final int IFD_PREVIEW_HINT = 5;
- private static final int ORF_MAKER_NOTE_HINT = 6;
- private static final int ORF_CAMERA_SETTINGS_HINT = 7;
- private static final int ORF_IMAGE_PROCESSING_HINT = 8;
- private static final int PEF_HINT = 9;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({IFD_TYPE_PRIMARY, IFD_TYPE_EXIF, IFD_TYPE_GPS, IFD_TYPE_INTEROPERABILITY,
+ IFD_TYPE_THUMBNAIL, IFD_TYPE_PREVIEW, IFD_TYPE_ORF_MAKER_NOTE,
+ IFD_TYPE_ORF_CAMERA_SETTINGS, IFD_TYPE_ORF_IMAGE_PROCESSING, IFD_TYPE_PEF})
+ public @interface IfdType {}
+
+ private static final int IFD_TYPE_PRIMARY = 0;
+ private static final int IFD_TYPE_EXIF = 1;
+ private static final int IFD_TYPE_GPS = 2;
+ private static final int IFD_TYPE_INTEROPERABILITY = 3;
+ private static final int IFD_TYPE_THUMBNAIL = 4;
+ private static final int IFD_TYPE_PREVIEW = 5;
+ private static final int IFD_TYPE_ORF_MAKER_NOTE = 6;
+ private static final int IFD_TYPE_ORF_CAMERA_SETTINGS = 7;
+ private static final int IFD_TYPE_ORF_IMAGE_PROCESSING = 8;
+ private static final int IFD_TYPE_PEF = 9;
+
// List of Exif tag groups
private static final ExifTag[][] EXIF_TAGS = new ExifTag[][] {
IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS,
@@ -1192,11 +1202,7 @@
new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_BYTE),
new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_BYTE)
};
- // List of indices of the indicated tag groups according to the EXIF_POINTER_TAGS
- private static final int[] EXIF_POINTER_TAG_HINTS = new int[] {
- IFD_PREVIEW_HINT, IFD_EXIF_HINT, IFD_GPS_HINT, IFD_INTEROPERABILITY_HINT,
- ORF_CAMERA_SETTINGS_HINT, ORF_IMAGE_PROCESSING_HINT
- };
+
// Tags for indicating the thumbnail offset and length
private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG);
@@ -1210,6 +1216,8 @@
private static final HashSet<String> sTagSetForCompatibility = new HashSet<>(Arrays.asList(
TAG_F_NUMBER, TAG_DIGITAL_ZOOM_RATIO, TAG_EXPOSURE_TIME, TAG_SUBJECT_DISTANCE,
TAG_GPS_TIMESTAMP));
+ // Mappings from tag number to IFD type for pointer tags.
+ private static final HashMap sExifPointerTagMap = new HashMap();
// See JPEG File Interchange Format Version 1.02.
// The following values are defined for handling JPEG streams. In this implementation, we are
@@ -1257,27 +1265,32 @@
private static final int IMAGE_TYPE_SRW = 11;
static {
- System.loadLibrary("media_jni");
- nativeInitRaw();
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// Build up the hash tables to look up Exif tags for reading Exif tags.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- sExifTagMapsForReading[hint] = new HashMap();
- sExifTagMapsForWriting[hint] = new HashMap();
- for (ExifTag tag : EXIF_TAGS[hint]) {
- sExifTagMapsForReading[hint].put(tag.number, tag);
- sExifTagMapsForWriting[hint].put(tag.name, tag);
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ sExifTagMapsForReading[ifdType] = new HashMap();
+ sExifTagMapsForWriting[ifdType] = new HashMap();
+ for (ExifTag tag : EXIF_TAGS[ifdType]) {
+ sExifTagMapsForReading[ifdType].put(tag.number, tag);
+ sExifTagMapsForWriting[ifdType].put(tag.name, tag);
}
}
+
+ // Build up the hash table to look up Exif pointer tags.
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[0].number, IFD_TYPE_PREVIEW); // 330
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[1].number, IFD_TYPE_EXIF); // 34665
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[2].number, IFD_TYPE_GPS); // 34853
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[3].number, IFD_TYPE_INTEROPERABILITY); // 40965
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[4].number, IFD_TYPE_ORF_CAMERA_SETTINGS); // 8224
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256
}
private final String mFilename;
private final FileDescriptor mSeekableFileDescriptor;
private final AssetManager.AssetInputStream mAssetInputStream;
private final boolean mIsInputStream;
- private boolean mIsRaw;
private int mMimeType;
private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN;
@@ -1507,7 +1520,7 @@
}
for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
- if (i == IFD_THUMBNAIL_HINT && !mHasThumbnail) {
+ if (i == IFD_TYPE_THUMBNAIL && !mHasThumbnail) {
continue;
}
final Object obj = sExifTagMapsForWriting[i].get(tag);
@@ -1660,71 +1673,44 @@
mAttributes[i] = new HashMap();
}
- if (HANDLE_RAW) {
- // Check file type
- in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
- mMimeType = getMimeType((BufferedInputStream) in);
+ // Check file type
+ in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
+ mMimeType = getMimeType((BufferedInputStream) in);
- switch (mMimeType) {
- case IMAGE_TYPE_JPEG: {
- getJpegAttributes(in, 0, IFD_TIFF_HINT); // 0 is offset
- break;
- }
- case IMAGE_TYPE_RAF: {
- getRafAttributes(in);
- break;
- }
- case IMAGE_TYPE_ORF: {
- getOrfAttributes(in);
- break;
- }
- case IMAGE_TYPE_RW2: {
- getRw2Attributes(in);
- break;
- }
- case IMAGE_TYPE_ARW:
- case IMAGE_TYPE_CR2:
- case IMAGE_TYPE_DNG:
- case IMAGE_TYPE_NEF:
- case IMAGE_TYPE_NRW:
- case IMAGE_TYPE_PEF:
- case IMAGE_TYPE_SRW:
- case IMAGE_TYPE_UNKNOWN: {
- getRawAttributes(in);
- break;
- }
- default: {
- break;
- }
+ switch (mMimeType) {
+ case IMAGE_TYPE_JPEG: {
+ getJpegAttributes(in, 0, IFD_TYPE_PRIMARY); // 0 is offset
+ break;
}
- // Set thumbnail image offset and length
- setThumbnailData(in);
- } else {
- if (mAssetInputStream != null) {
- long asset = mAssetInputStream.getNativeAsset();
- if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
- return;
- }
- } else if (mSeekableFileDescriptor != null) {
- if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
- mSeekableFileDescriptor))) {
- return;
- }
- } else {
- in.mark(JPEG_SIGNATURE.length);
- byte[] signatureBytes = new byte[JPEG_SIGNATURE.length];
- if (in.read(signatureBytes) != JPEG_SIGNATURE.length) {
- throw new EOFException();
- }
- in.reset();
- if (!isJpegFormat(signatureBytes) && handleRawResult(
- nativeGetRawAttributesFromInputStream(in))) {
- return;
- }
+ case IMAGE_TYPE_RAF: {
+ getRafAttributes(in);
+ break;
}
- // Process JPEG input stream
- getJpegAttributes(in, 0, IFD_TIFF_HINT);
+ case IMAGE_TYPE_ORF: {
+ getOrfAttributes(in);
+ break;
+ }
+ case IMAGE_TYPE_RW2: {
+ getRw2Attributes(in);
+ break;
+ }
+ case IMAGE_TYPE_ARW:
+ case IMAGE_TYPE_CR2:
+ case IMAGE_TYPE_DNG:
+ case IMAGE_TYPE_NEF:
+ case IMAGE_TYPE_NRW:
+ case IMAGE_TYPE_PEF:
+ case IMAGE_TYPE_SRW:
+ case IMAGE_TYPE_UNKNOWN: {
+ getRawAttributes(in);
+ break;
+ }
+ default: {
+ break;
+ }
}
+ // Set thumbnail image offset and length
+ setThumbnailData(in);
} catch (IOException e) {
// Ignore exceptions in order to keep the compatibility with the old versions of
// ExifInterface.
@@ -1742,36 +1728,6 @@
}
}
- private boolean handleRawResult(HashMap map) {
- if (map == null) {
- if (DEBUG) {
- Log.d(TAG, "Raw image file not detected");
- }
- return false;
- }
-
- // Mark for disabling the save feature.
- mIsRaw = true;
-
- String value = (String) map.remove(TAG_HAS_THUMBNAIL);
- mHasThumbnail = value != null && value.equalsIgnoreCase("true");
- value = (String) map.remove(TAG_THUMBNAIL_OFFSET);
- if (value != null) {
- mThumbnailOffset = Integer.parseInt(value);
- }
- value = (String) map.remove(TAG_THUMBNAIL_LENGTH);
- if (value != null) {
- mThumbnailLength = Integer.parseInt(value);
- }
- mThumbnailBytes = (byte[]) map.remove(TAG_THUMBNAIL_DATA);
-
- for (Map.Entry entry : (Set<Map.Entry>) map.entrySet()) {
- setAttribute((String) entry.getKey(), (String) entry.getValue());
- }
-
- return true;
- }
-
private static boolean isSeekableFD(FileDescriptor fd) throws IOException {
try {
Os.lseek(fd, 0, OsConstants.SEEK_CUR);
@@ -1800,9 +1756,9 @@
* and make a single call rather than multiple calls for each attribute.
*/
public void saveAttributes() throws IOException {
- if (mIsRaw) {
+ if (mMimeType != IMAGE_TYPE_JPEG) {
throw new UnsupportedOperationException(
- "ExifInterface does not support saving attributes on RAW formats.");
+ "ExifInterface only supports saving attributes on JPEG formats.");
}
if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
throw new UnsupportedOperationException(
@@ -1955,9 +1911,9 @@
}
ExifAttribute imageLengthAttribute =
- (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_LENGTH);
+ (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_LENGTH);
ExifAttribute imageWidthAttribute =
- (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_WIDTH);
+ (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_WIDTH);
if (imageLengthAttribute != null && imageWidthAttribute != null) {
int imageLength = imageLengthAttribute.getIntValue(mExifByteOrder);
int imageWidth = imageWidthAttribute.getIntValue(mExifByteOrder);
@@ -2226,9 +2182,9 @@
*
* @param inputStream The input stream that starts with the JPEG data.
* @param jpegOffset The offset value in input stream for JPEG data.
- * @param imageTypes The image type from which to retrieve metadata. Use IFD_TIFF_HINT for
- * primary image, IFD_PREVIEW_HINT for preview image, and
- * IFD_THUMBNAIL_HINT for thumbnail image.
+ * @param imageTypes The image type from which to retrieve metadata. Use IFD_TYPE_PRIMARY for
+ * primary image, IFD_TYPE_PREVIEW for preview image, and
+ * IFD_TYPE_THUMBNAIL for thumbnail image.
* @throws IOException If the data contains invalid JPEG markers, offsets, or length values.
*/
private void getJpegAttributes(InputStream inputStream, int jpegOffset, int imageType)
@@ -2329,7 +2285,7 @@
}
length = 0;
if (getAttribute(TAG_USER_COMMENT) == null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_USER_COMMENT, ExifAttribute.createString(
+ mAttributes[IFD_TYPE_EXIF].put(TAG_USER_COMMENT, ExifAttribute.createString(
new String(bytes, ASCII)));
}
break;
@@ -2389,12 +2345,12 @@
parseTiffHeaders(dataInputStream, exifBytes.length);
// Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6.
- readImageFileDirectory(dataInputStream, IFD_TIFF_HINT);
+ readImageFileDirectory(dataInputStream, IFD_TYPE_PRIMARY);
// Update ImageLength/Width tags for all image data.
- updateImageSizeValues(in, IFD_TIFF_HINT);
- updateImageSizeValues(in, IFD_PREVIEW_HINT);
- updateImageSizeValues(in, IFD_THUMBNAIL_HINT);
+ updateImageSizeValues(in, IFD_TYPE_PRIMARY);
+ updateImageSizeValues(in, IFD_TYPE_PREVIEW);
+ updateImageSizeValues(in, IFD_TYPE_THUMBNAIL);
// Check if each image data is in valid position.
validateImages(in);
@@ -2403,7 +2359,7 @@
// PEF files contain a MakerNote data, which contains the data for ColorSpace tag.
// See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
ExifAttribute makerNoteAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
if (makerNoteAttribute != null) {
// Create an ordered DataInputStream for MakerNote
ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
@@ -2414,13 +2370,13 @@
makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
// Read IFD data from MakerNote
- readImageFileDirectory(makerNoteDataInputStream, PEF_HINT);
+ readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_PEF);
// Update ColorSpace tag
ExifAttribute colorSpaceAttribute =
- (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE);
+ (ExifAttribute) mAttributes[IFD_TYPE_PEF].get(TAG_COLOR_SPACE);
if (colorSpaceAttribute != null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute);
+ mAttributes[IFD_TYPE_EXIF].put(TAG_COLOR_SPACE, colorSpaceAttribute);
}
}
}
@@ -2453,7 +2409,7 @@
in.reset();
// Retrieve JPEG image metadata
- getJpegAttributes(in, rafJpegOffset, IFD_PREVIEW_HINT);
+ getJpegAttributes(in, rafJpegOffset, IFD_TYPE_PREVIEW);
// Skip to CFA header offset.
// A while loop is used because the skip method may not be able to skip the requested amount
@@ -2490,8 +2446,8 @@
ExifAttribute.createUShort(imageLength, mExifByteOrder);
ExifAttribute imageWidthAttribute =
ExifAttribute.createUShort(imageWidth, mExifByteOrder);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
if (DEBUG) {
Log.d(TAG, "Updated to length: " + imageLength + ", width: " + imageWidth);
}
@@ -2520,7 +2476,7 @@
// proprietary tags and therefore does not have offical documentation
// See GetOlympusPreviewImage() in piex.cc & http://www.exiv2.org/tags-olympus.html
ExifAttribute makerNoteAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
if (makerNoteAttribute != null) {
// Create an ordered DataInputStream for MakerNote
ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
@@ -2542,18 +2498,18 @@
}
// Read IFD data from MakerNote
- readImageFileDirectory(makerNoteDataInputStream, ORF_MAKER_NOTE_HINT);
+ readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_ORF_MAKER_NOTE);
// Retrieve & update preview image offset & length values
ExifAttribute imageLengthAttribute = (ExifAttribute)
- mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_START);
+ mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_START);
ExifAttribute bitsPerSampleAttribute = (ExifAttribute)
- mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
+ mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
if (imageLengthAttribute != null && bitsPerSampleAttribute != null) {
- mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT,
+ mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT,
imageLengthAttribute);
- mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
bitsPerSampleAttribute);
}
@@ -2561,7 +2517,7 @@
// Retrieve primary image length & width values
// See piex.cc GetOlympusPreviewImage()
ExifAttribute aspectFrameAttribute = (ExifAttribute)
- mAttributes[ORF_IMAGE_PROCESSING_HINT].get(TAG_ORF_ASPECT_FRAME);
+ mAttributes[IFD_TYPE_ORF_IMAGE_PROCESSING].get(TAG_ORF_ASPECT_FRAME);
if (aspectFrameAttribute != null) {
int[] aspectFrameValues = new int[4];
aspectFrameValues = (int[]) aspectFrameAttribute.getValue(mExifByteOrder);
@@ -2580,8 +2536,8 @@
ExifAttribute primaryImageLengthAttribute =
ExifAttribute.createUShort(primaryImageLength, mExifByteOrder);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
}
}
}
@@ -2596,47 +2552,19 @@
// Retrieve preview and/or thumbnail image data
ExifAttribute jpgFromRawAttribute =
- (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_JPG_FROM_RAW);
+ (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_JPG_FROM_RAW);
if (jpgFromRawAttribute != null) {
- getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_PREVIEW_HINT);
+ getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_TYPE_PREVIEW);
}
// Set ISO tag value if necessary
ExifAttribute rw2IsoAttribute =
- (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_ISO);
+ (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO);
ExifAttribute exifIsoAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_ISO_SPEED_RATINGS);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_ISO_SPEED_RATINGS);
if (rw2IsoAttribute != null && exifIsoAttribute == null) {
// Place this attribute only if it doesn't exist
- mAttributes[IFD_EXIF_HINT].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
- }
- }
-
- // PEF is TIFF-based and contains 3 IFDs. It also contains a MakerNote data, which contains the
- // ColorSpace tag data.
- // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
- private void getPefAttributes(InputStream in) throws IOException {
- // Retrieve ColorSpace tag
- ExifAttribute makerNoteAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
- if (makerNoteAttribute != null) {
- // Create an ordered DataInputStream for MakerNote
- ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
- new ByteOrderAwarenessDataInputStream(makerNoteAttribute.bytes);
- makerNoteDataInputStream.setByteOrder(mExifByteOrder);
-
- // Seek to MakerNote data
- makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
-
- // Read IFD data from MakerNote
- readImageFileDirectory(makerNoteDataInputStream, PEF_HINT);
-
- // Update ColorSpace tag
- ExifAttribute colorSpaceAttribute =
- (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE);
- if (colorSpaceAttribute != null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute);
- }
+ mAttributes[IFD_TYPE_EXIF].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
}
}
@@ -2754,25 +2682,25 @@
// The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL);
if (valueOfDateTimeOriginal != null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_DATETIME,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME,
ExifAttribute.createString(valueOfDateTimeOriginal));
}
// Add the default value.
if (getAttribute(TAG_IMAGE_WIDTH) == null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (getAttribute(TAG_IMAGE_LENGTH) == null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (getAttribute(TAG_ORIENTATION) == null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_ORIENTATION,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (getAttribute(TAG_LIGHT_SOURCE) == null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_LIGHT_SOURCE,
+ mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE,
ExifAttribute.createULong(0, mExifByteOrder));
}
}
@@ -2824,8 +2752,8 @@
}
// Reads image file directory, which is a tag group in EXIF.
- private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint)
- throws IOException {
+ private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream,
+ @IfdType int ifdType) throws IOException {
if (dataInputStream.peek() + 2 > dataInputStream.mLength) {
// Return if there is no data from the offset.
return;
@@ -2850,12 +2778,12 @@
long nextEntryOffset = dataInputStream.peek() + 4;
// Look up a corresponding tag from tag number
- ExifTag tag = (ExifTag) sExifTagMapsForReading[hint].get(tagNumber);
+ ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber);
if (DEBUG) {
- Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " +
- "numberOfComponents: %d", hint, tagNumber, tag != null ? tag.name : null,
- dataFormat, numberOfComponents));
+ Log.d(TAG, String.format("ifdType: %d, tagNumber: %d, tagName: %s, dataFormat: %d, "
+ + "numberOfComponents: %d", ifdType, tagNumber,
+ tag != null ? tag.name : null, dataFormat, numberOfComponents));
}
if (tag == null || dataFormat <= 0 ||
@@ -2882,7 +2810,8 @@
if (tag.name == TAG_MAKER_NOTE) {
// Save offset value for reading thumbnail
mOrfMakerNoteOffset = offset;
- } else if (hint == ORF_MAKER_NOTE_HINT && tag.name == TAG_ORF_THUMBNAIL_IMAGE) {
+ } else if (ifdType == IFD_TYPE_ORF_MAKER_NOTE
+ && tag.name == TAG_ORF_THUMBNAIL_IMAGE) {
// Retrieve & update values for thumbnail offset and length values for ORF
mOrfThumbnailOffset = offset;
mOrfThumbnailLength = numberOfComponents;
@@ -2894,10 +2823,10 @@
ExifAttribute jpegInterchangeFormatLengthAttribute =
ExifAttribute.createULong(mOrfThumbnailLength, mExifByteOrder);
- mAttributes[IFD_THUMBNAIL_HINT].put(TAG_COMPRESSION, compressionAttribute);
- mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_COMPRESSION, compressionAttribute);
+ mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT,
jpegInterchangeFormatAttribute);
- mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
jpegInterchangeFormatLengthAttribute);
}
} else if (mMimeType == IMAGE_TYPE_RW2) {
@@ -2916,12 +2845,12 @@
}
// Recursively parse IFD when a IFD pointer tag appears.
- int innerIfdHint = getIfdHintFromTagNumber(tagNumber);
+ Object nextIfdType = sExifPointerTagMap.get(tagNumber);
if (DEBUG) {
- Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount);
+ Log.d(TAG, "nextIfdType: " + nextIfdType + " byteCount: " + byteCount);
}
- if (innerIfdHint >= 0) {
+ if (nextIfdType != null) {
long offset = -1L;
// Get offset from data field
switch (dataFormat) {
@@ -2952,7 +2881,7 @@
}
if (offset > 0L && offset < dataInputStream.mLength) {
dataInputStream.seek(offset);
- readImageFileDirectory(dataInputStream, innerIfdHint);
+ readImageFileDirectory(dataInputStream, (int) nextIfdType);
} else {
Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset);
}
@@ -2964,7 +2893,7 @@
byte[] bytes = new byte[byteCount];
dataInputStream.readFully(bytes);
ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
- mAttributes[hint].put(tag.name, attribute);
+ mAttributes[ifdType].put(tag.name, attribute);
// DNG files have a DNG Version tag specifying the version of specifications that the
// image file is following.
@@ -2998,11 +2927,11 @@
// since the first IFD offset is at least 8.
if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) {
dataInputStream.seek(nextIfdOffset);
- if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
+ if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
// Do not overwrite thumbnail IFD data if it alreay exists.
- readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
- } else if (mAttributes[IFD_PREVIEW_HINT].isEmpty()) {
- readImageFileDirectory(dataInputStream, IFD_PREVIEW_HINT);
+ readImageFileDirectory(dataInputStream, IFD_TYPE_THUMBNAIL);
+ } else if (mAttributes[IFD_TYPE_PREVIEW].isEmpty()) {
+ readImageFileDirectory(dataInputStream, IFD_TYPE_PREVIEW);
}
}
}
@@ -3037,7 +2966,7 @@
// Sets thumbnail offset & length attributes based on JpegInterchangeFormat or StripOffsets tags
private void setThumbnailData(InputStream in) throws IOException {
- HashMap thumbnailData = mAttributes[IFD_THUMBNAIL_HINT];
+ HashMap thumbnailData = mAttributes[IFD_TYPE_THUMBNAIL];
ExifAttribute compressionAttribute =
(ExifAttribute) thumbnailData.get(TAG_COMPRESSION);
@@ -3207,21 +3136,21 @@
// Validate primary, preview, thumbnail image data by comparing image size
private void validateImages(InputStream in) throws IOException {
// Swap images based on size (primary > preview > thumbnail)
- swapBasedOnImageSize(IFD_TIFF_HINT, IFD_PREVIEW_HINT);
- swapBasedOnImageSize(IFD_TIFF_HINT, IFD_THUMBNAIL_HINT);
- swapBasedOnImageSize(IFD_PREVIEW_HINT, IFD_THUMBNAIL_HINT);
+ swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW);
+ swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL);
+ swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL);
// Check whether thumbnail image exists and whether preview image satisfies the thumbnail
// image requirements
- if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
- if (isThumbnail(mAttributes[IFD_PREVIEW_HINT])) {
- mAttributes[IFD_THUMBNAIL_HINT] = mAttributes[IFD_PREVIEW_HINT];
- mAttributes[IFD_PREVIEW_HINT] = new HashMap();
+ if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
+ if (isThumbnail(mAttributes[IFD_TYPE_PREVIEW])) {
+ mAttributes[IFD_TYPE_THUMBNAIL] = mAttributes[IFD_TYPE_PREVIEW];
+ mAttributes[IFD_TYPE_PREVIEW] = new HashMap();
}
}
// Check if the thumbnail image satisfies the thumbnail size requirements
- if (!isThumbnail(mAttributes[IFD_THUMBNAIL_HINT])) {
+ if (!isThumbnail(mAttributes[IFD_TYPE_THUMBNAIL])) {
Log.d(TAG, "No image meets the size requirements of a thumbnail image.");
}
}
@@ -3305,9 +3234,9 @@
if (newSubfileTypeValue == ORIGINAL_RESOLUTION_IMAGE) {
// Update only for the primary image (OriginalResolutionImage)
ExifAttribute pixelXDimAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_X_DIMENSION);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_X_DIMENSION);
ExifAttribute pixelYDimAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_Y_DIMENSION);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_Y_DIMENSION);
if (pixelXDimAttribute != null && pixelYDimAttribute != null) {
mAttributes[imageType].put(TAG_IMAGE_WIDTH, pixelXDimAttribute);
@@ -3320,16 +3249,6 @@
}
}
- // Gets the corresponding IFD group index of the given tag number for writing Exif Tags.
- private static int getIfdHintFromTagNumber(int tagNumber) {
- for (int i = 0; i < EXIF_POINTER_TAG_HINTS.length; ++i) {
- if (EXIF_POINTER_TAGS[i].number == tagNumber) {
- return EXIF_POINTER_TAG_HINTS[i];
- }
- }
- return -1;
- }
-
// Writes an Exif segment into the given output stream.
private int writeExifSegment(ByteOrderAwarenessDataOutputStream dataOutputStream,
int exifOffsetFromBeginning) throws IOException {
@@ -3346,33 +3265,33 @@
removeAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name);
// Remove null value tags.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- for (Object obj : mAttributes[hint].entrySet().toArray()) {
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ for (Object obj : mAttributes[ifdType].entrySet().toArray()) {
final Map.Entry entry = (Map.Entry) obj;
if (entry.getValue() == null) {
- mAttributes[hint].remove(entry.getKey());
+ mAttributes[ifdType].remove(entry.getKey());
}
}
}
// Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
// offset when there is one or more tags in the thumbnail IFD.
- if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name,
+ if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
ExifAttribute.createULong(0, mExifByteOrder));
}
- if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name,
+ if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
ExifAttribute.createULong(0, mExifByteOrder));
}
- if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
- mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name,
+ if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
+ mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (mHasThumbnail) {
- mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
ExifAttribute.createULong(0, mExifByteOrder));
- mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
ExifAttribute.createULong(mThumbnailLength, mExifByteOrder));
}
@@ -3392,15 +3311,15 @@
// Calculate IFD offsets.
int position = 8;
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- if (!mAttributes[hint].isEmpty()) {
- ifdOffsets[hint] = position;
- position += 2 + mAttributes[hint].size() * 12 + 4 + ifdDataSizes[hint];
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ if (!mAttributes[ifdType].isEmpty()) {
+ ifdOffsets[ifdType] = position;
+ position += 2 + mAttributes[ifdType].size() * 12 + 4 + ifdDataSizes[ifdType];
}
}
if (mHasThumbnail) {
int thumbnailOffset = position;
- mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
ExifAttribute.createULong(thumbnailOffset, mExifByteOrder));
mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
position += mThumbnailLength;
@@ -3417,17 +3336,17 @@
}
// Update IFD pointer tags with the calculated offsets.
- if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name,
- ExifAttribute.createULong(ifdOffsets[IFD_EXIF_HINT], mExifByteOrder));
+ if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
+ ExifAttribute.createULong(ifdOffsets[IFD_TYPE_EXIF], mExifByteOrder));
}
- if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name,
- ExifAttribute.createULong(ifdOffsets[IFD_GPS_HINT], mExifByteOrder));
+ if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
+ ExifAttribute.createULong(ifdOffsets[IFD_TYPE_GPS], mExifByteOrder));
}
- if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
- mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
- ifdOffsets[IFD_INTEROPERABILITY_HINT], mExifByteOrder));
+ if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
+ mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
+ ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder));
}
// Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
@@ -3440,17 +3359,18 @@
dataOutputStream.writeUnsignedInt(IFD_OFFSET);
// Write IFD groups. See JEITA CP-3451C Section 4.5.8. Figure 9.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- if (!mAttributes[hint].isEmpty()) {
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ if (!mAttributes[ifdType].isEmpty()) {
// See JEITA CP-3451C Section 4.6.2: IFD structure.
// Write entry count
- dataOutputStream.writeUnsignedShort(mAttributes[hint].size());
+ dataOutputStream.writeUnsignedShort(mAttributes[ifdType].size());
// Write entry info
- int dataOffset = ifdOffsets[hint] + 2 + mAttributes[hint].size() * 12 + 4;
- for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+ int dataOffset = ifdOffsets[ifdType] + 2 + mAttributes[ifdType].size() * 12 + 4;
+ for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) {
// Convert tag name to tag number.
- final ExifTag tag = (ExifTag) sExifTagMapsForWriting[hint].get(entry.getKey());
+ final ExifTag tag =
+ (ExifTag) sExifTagMapsForWriting[ifdType].get(entry.getKey());
final int tagNumber = tag.number;
final ExifAttribute attribute = (ExifAttribute) entry.getValue();
final int size = attribute.size();
@@ -3475,14 +3395,14 @@
// Write the next offset. It writes the offset of thumbnail IFD if there is one or
// more tags in the thumbnail IFD when the current IFD is the primary image TIFF
// IFD; Otherwise 0.
- if (hint == 0 && !mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
- dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]);
+ if (ifdType == 0 && !mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
+ dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_TYPE_THUMBNAIL]);
} else {
dataOutputStream.writeUnsignedInt(0);
}
// Write values of data field exceeding 4 bytes after the next offset.
- for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+ for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) {
ExifAttribute attribute = (ExifAttribute) entry.getValue();
if (attribute.bytes.length > 4) {
@@ -3809,9 +3729,9 @@
}
// Swaps image data based on image size
- private void swapBasedOnImageSize(int firstImageHint, int secondImageHint)
+ private void swapBasedOnImageSize(@IfdType int firstIfdType, @IfdType int secondIfdType)
throws IOException {
- if (mAttributes[firstImageHint].isEmpty() || mAttributes[secondImageHint].isEmpty()) {
+ if (mAttributes[firstIfdType].isEmpty() || mAttributes[secondIfdType].isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Cannot perform swap since only one image data exists");
}
@@ -3819,13 +3739,13 @@
}
ExifAttribute firstImageLengthAttribute =
- (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_LENGTH);
+ (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_LENGTH);
ExifAttribute firstImageWidthAttribute =
- (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_WIDTH);
+ (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_WIDTH);
ExifAttribute secondImageLengthAttribute =
- (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_LENGTH);
+ (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_LENGTH);
ExifAttribute secondImageWidthAttribute =
- (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_WIDTH);
+ (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_WIDTH);
if (firstImageLengthAttribute == null || firstImageWidthAttribute == null) {
if (DEBUG) {
@@ -3843,9 +3763,9 @@
if (firstImageLengthValue < secondImageLengthValue &&
firstImageWidthValue < secondImageWidthValue) {
- HashMap tempMap = mAttributes[firstImageHint];
- mAttributes[firstImageHint] = mAttributes[secondImageHint];
- mAttributes[secondImageHint] = tempMap;
+ HashMap tempMap = mAttributes[firstIfdType];
+ mAttributes[firstIfdType] = mAttributes[secondIfdType];
+ mAttributes[secondIfdType] = tempMap;
}
}
}
@@ -3864,12 +3784,4 @@
}
return false;
}
-
- // JNI methods for RAW formats.
- private static native void nativeInitRaw();
- private static native byte[] nativeGetThumbnailFromAsset(
- long asset, int thumbnailOffset, int thumbnailLength);
- private static native HashMap nativeGetRawAttributesFromAsset(long asset);
- private static native HashMap nativeGetRawAttributesFromFileDescriptor(FileDescriptor fd);
- private static native HashMap nativeGetRawAttributesFromInputStream(InputStream in);
}
\ No newline at end of file
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index fbc8615..4c49f67 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -226,10 +226,12 @@
ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
OsConstants.SOCK_SEQPACKET);
MidiInputPort inputPort = new MidiInputPort(pair[0], portNumber);
- // Configure the server-side socket in non-blocking mode to avoid stalling
- // the entire MIDI framework if client app code gets stuck inside 'onSend'
- // handler.
- IoUtils.setBlocking(pair[0].getFileDescriptor(), false);
+ // Undo the default blocking-mode of the server-side socket for
+ // physical devices to avoid stalling the Java device handler if
+ // client app code gets stuck inside 'onSend' handler.
+ if (mDeviceInfo.getType() != MidiDeviceInfo.TYPE_VIRTUAL) {
+ IoUtils.setBlocking(pair[0].getFileDescriptor(), false);
+ }
MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber];
synchronized (dispatcher) {
dispatcher.getSender().connect(inputPort);
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 2c28a10..dcd5057 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -3,7 +3,6 @@
LOCAL_SRC_FILES:= \
android_media_AmrInputStream.cpp \
- android_media_ExifInterface.cpp \
android_media_ImageWriter.cpp \
android_media_ImageReader.cpp \
android_media_MediaCrypto.cpp \
diff --git a/media/jni/android_media_ExifInterface.cpp b/media/jni/android_media_ExifInterface.cpp
deleted file mode 100644
index 10b31706..0000000
--- a/media/jni/android_media_ExifInterface.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ExifInterface_JNI"
-
-#include "android_media_Utils.h"
-
-#include "android/graphics/CreateJavaOutputStreamAdaptor.h"
-#include "src/piex_types.h"
-#include "src/piex.h"
-
-#include <jni.h>
-#include <JNIHelp.h>
-#include <androidfw/Asset.h>
-#include <android_runtime/AndroidRuntime.h>
-#include <android/graphics/Utils.h>
-#include <nativehelper/ScopedLocalRef.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/KeyedVector.h>
-
-// ----------------------------------------------------------------------------
-
-using namespace android;
-
-static const char kJpegSignatureChars[] = {(char)0xff, (char)0xd8, (char)0xff};
-static const int kJpegSignatureSize = 3;
-
-#define FIND_CLASS(var, className) \
- var = env->FindClass(className); \
- LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find method " fieldName);
-
-struct HashMapFields {
- jmethodID init;
- jmethodID put;
-};
-
-struct fields_t {
- HashMapFields hashMap;
- jclass hashMapClassId;
-};
-
-static fields_t gFields;
-
-static jobject KeyedVectorToHashMap(JNIEnv *env, KeyedVector<String8, String8> const &map) {
- jclass clazz = gFields.hashMapClassId;
- jobject hashMap = env->NewObject(clazz, gFields.hashMap.init);
- for (size_t i = 0; i < map.size(); ++i) {
- jstring jkey = env->NewStringUTF(map.keyAt(i).string());
- jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
- env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jvalue);
- env->DeleteLocalRef(jkey);
- env->DeleteLocalRef(jvalue);
- }
- return hashMap;
-}
-
-extern "C" {
-
-// -------------------------- ExifInterface methods ---------------------------
-
-static void ExifInterface_initRaw(JNIEnv *env) {
- jclass clazz;
- FIND_CLASS(clazz, "java/util/HashMap");
- gFields.hashMapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
-
- GET_METHOD_ID(gFields.hashMap.init, clazz, "<init>", "()V");
- GET_METHOD_ID(gFields.hashMap.put, clazz, "put",
- "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-}
-
-static bool is_asset_stream(const SkStream& stream) {
- return stream.hasLength() && stream.hasPosition();
-}
-
-static jobject ExifInterface_getThumbnailFromAsset(
- JNIEnv* env, jclass /* clazz */, jlong jasset, jint jthumbnailOffset,
- jint jthumbnailLength) {
- Asset* asset = reinterpret_cast<Asset*>(jasset);
- std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset));
-
- std::unique_ptr<jbyte[]> thumbnailData(new jbyte[(int)jthumbnailLength]);
- if (thumbnailData.get() == NULL) {
- ALOGI("No memory to get thumbnail");
- return NULL;
- }
-
- // Do not know the current offset. So rewind it.
- stream->rewind();
-
- // Read thumbnail.
- stream->skip((int)jthumbnailOffset);
- stream->read((void*)thumbnailData.get(), (int)jthumbnailLength);
-
- // Copy to the byte array.
- jbyteArray byteArray = env->NewByteArray(jthumbnailLength);
- env->SetByteArrayRegion(byteArray, 0, jthumbnailLength, thumbnailData.get());
- return byteArray;
-}
-
-static jobject getRawAttributes(JNIEnv* env, SkStream* stream, bool returnThumbnail) {
- std::unique_ptr<SkStream> streamDeleter(stream);
-
- std::unique_ptr<::piex::StreamInterface> piexStream;
- if (is_asset_stream(*stream)) {
- piexStream.reset(new AssetStream(streamDeleter.release()));
- } else {
- piexStream.reset(new BufferedStream(streamDeleter.release()));
- }
-
- piex::PreviewImageData image_data;
-
- if (!GetExifFromRawImage(piexStream.get(), String8("[piex stream]"), image_data)) {
- return NULL;
- }
-
- KeyedVector<String8, String8> map;
-
- if (image_data.thumbnail.length > 0
- && image_data.thumbnail.format == ::piex::Image::kJpegCompressed) {
- map.add(String8("HasThumbnail"), String8("true"));
- map.add(String8("ThumbnailOffset"), String8::format("%d", image_data.thumbnail.offset));
- map.add(String8("ThumbnailLength"), String8::format("%d", image_data.thumbnail.length));
- } else {
- map.add(String8("HasThumbnail"), String8("false"));
- }
-
- map.add(
- String8("Orientation"),
- String8::format("%u", image_data.exif_orientation));
- map.add(
- String8("ImageWidth"),
- String8::format("%u", image_data.full_width));
- map.add(
- String8("ImageLength"),
- String8::format("%u", image_data.full_height));
-
- // Current PIEX does not have LightSource information while JPEG version of
- // EXIFInterface always declares the light source field. For the
- // compatibility, it provides the default value of the light source field.
- map.add(String8("LightSource"), String8("0"));
-
- if (!image_data.maker.empty()) {
- map.add(String8("Make"), String8(image_data.maker.c_str()));
- }
-
- if (!image_data.model.empty()) {
- map.add(String8("Model"), String8(image_data.model.c_str()));
- }
-
- if (!image_data.date_time.empty()) {
- map.add(String8("DateTime"), String8(image_data.date_time.c_str()));
- }
-
- if (image_data.iso) {
- map.add(
- String8("ISOSpeedRatings"),
- String8::format("%u", image_data.iso));
- }
-
- if (image_data.exposure_time.numerator != 0
- && image_data.exposure_time.denominator != 0) {
- double exposureTime =
- (double)image_data.exposure_time.numerator
- / image_data.exposure_time.denominator;
-
- const char* format;
- if (exposureTime < 0.01) {
- format = "%6.4f";
- } else {
- format = "%5.3f";
- }
- map.add(String8("ExposureTime"), String8::format(format, exposureTime));
- }
-
- if (image_data.fnumber.numerator != 0
- && image_data.fnumber.denominator != 0) {
- double fnumber =
- (double)image_data.fnumber.numerator
- / image_data.fnumber.denominator;
- map.add(String8("FNumber"), String8::format("%5.3f", fnumber));
- }
-
- if (image_data.focal_length.numerator != 0
- && image_data.focal_length.denominator != 0) {
- map.add(
- String8("FocalLength"),
- String8::format(
- "%u/%u",
- image_data.focal_length.numerator,
- image_data.focal_length.denominator));
- }
-
- if (image_data.gps.is_valid) {
- if (image_data.gps.latitude[0].denominator != 0
- && image_data.gps.latitude[1].denominator != 0
- && image_data.gps.latitude[2].denominator != 0) {
- map.add(
- String8("GPSLatitude"),
- String8::format(
- "%u/%u,%u/%u,%u/%u",
- image_data.gps.latitude[0].numerator,
- image_data.gps.latitude[0].denominator,
- image_data.gps.latitude[1].numerator,
- image_data.gps.latitude[1].denominator,
- image_data.gps.latitude[2].numerator,
- image_data.gps.latitude[2].denominator));
- }
-
- if (image_data.gps.latitude_ref) {
- char str[2];
- str[0] = image_data.gps.latitude_ref;
- str[1] = 0;
- map.add(String8("GPSLatitudeRef"), String8(str));
- }
-
- if (image_data.gps.longitude[0].denominator != 0
- && image_data.gps.longitude[1].denominator != 0
- && image_data.gps.longitude[2].denominator != 0) {
- map.add(
- String8("GPSLongitude"),
- String8::format(
- "%u/%u,%u/%u,%u/%u",
- image_data.gps.longitude[0].numerator,
- image_data.gps.longitude[0].denominator,
- image_data.gps.longitude[1].numerator,
- image_data.gps.longitude[1].denominator,
- image_data.gps.longitude[2].numerator,
- image_data.gps.longitude[2].denominator));
- }
-
- if (image_data.gps.longitude_ref) {
- char str[2];
- str[0] = image_data.gps.longitude_ref;
- str[1] = 0;
- map.add(String8("GPSLongitudeRef"), String8(str));
- }
-
- if (image_data.gps.altitude.denominator != 0) {
- map.add(
- String8("GPSAltitude"),
- String8::format("%u/%u",
- image_data.gps.altitude.numerator,
- image_data.gps.altitude.denominator));
-
- map.add(
- String8("GPSAltitudeRef"),
- String8(image_data.gps.altitude_ref ? "1" : "0"));
- }
-
- if (image_data.gps.time_stamp[0].denominator != 0
- && image_data.gps.time_stamp[1].denominator != 0
- && image_data.gps.time_stamp[2].denominator != 0) {
- map.add(
- String8("GPSTimeStamp"),
- String8::format(
- "%02u:%02u:%02u",
- image_data.gps.time_stamp[0].numerator
- / image_data.gps.time_stamp[0].denominator,
- image_data.gps.time_stamp[1].numerator
- / image_data.gps.time_stamp[1].denominator,
- image_data.gps.time_stamp[2].numerator
- / image_data.gps.time_stamp[2].denominator));
- }
-
- if (!image_data.gps.date_stamp.empty()) {
- map.add(
- String8("GPSDateStamp"),
- String8(image_data.gps.date_stamp.c_str()));
- }
- }
-
- jobject hashMap = KeyedVectorToHashMap(env, map);
-
- if (returnThumbnail) {
- std::unique_ptr<jbyte[]> thumbnailData(new jbyte[image_data.thumbnail.length]);
- if (thumbnailData.get() == NULL) {
- ALOGE("No memory to parse a thumbnail");
- return NULL;
- }
- jbyteArray jthumbnailByteArray = env->NewByteArray(image_data.thumbnail.length);
- if (jthumbnailByteArray == NULL) {
- ALOGE("No memory to parse a thumbnail");
- return NULL;
- }
- piexStream.get()->GetData(image_data.thumbnail.offset, image_data.thumbnail.length,
- (uint8_t*)thumbnailData.get());
- env->SetByteArrayRegion(
- jthumbnailByteArray, 0, image_data.thumbnail.length, thumbnailData.get());
- jstring jkey = env->NewStringUTF(String8("ThumbnailData"));
- env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jthumbnailByteArray);
- env->DeleteLocalRef(jkey);
- env->DeleteLocalRef(jthumbnailByteArray);
- }
- return hashMap;
-}
-
-static jobject ExifInterface_getRawAttributesFromAsset(
- JNIEnv* env, jclass /* clazz */, jlong jasset) {
- std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]);
- if (jpegSignature.get() == NULL) {
- ALOGE("No enough memory to parse");
- return NULL;
- }
-
- Asset* asset = reinterpret_cast<Asset*>(jasset);
- std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset));
-
- if (stream.get()->read(jpegSignature.get(), kJpegSignatureSize) != kJpegSignatureSize) {
- // Rewind the stream.
- stream.get()->rewind();
-
- ALOGI("Corrupted image.");
- return NULL;
- }
-
- // Rewind the stream.
- stream.get()->rewind();
-
- if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) {
- ALOGI("Should be a JPEG stream.");
- return NULL;
- }
-
- // Try to parse from the given stream.
- jobject result = getRawAttributes(env, stream.get(), false);
-
- // Rewind the stream for the chance to read JPEG.
- if (result == NULL) {
- stream.get()->rewind();
- }
- return result;
-}
-
-static jobject ExifInterface_getRawAttributesFromFileDescriptor(
- JNIEnv* env, jclass /* clazz */, jobject jfileDescriptor) {
- std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]);
- if (jpegSignature.get() == NULL) {
- ALOGE("No enough memory to parse");
- return NULL;
- }
-
- int fd = jniGetFDFromFileDescriptor(env, jfileDescriptor);
- if (fd < 0) {
- ALOGI("Invalid file descriptor");
- return NULL;
- }
-
- // Restore the file descriptor's offset on exiting this function.
- AutoFDSeek autoRestore(fd);
-
- int dupFd = dup(fd);
-
- FILE* file = fdopen(dupFd, "r");
- if (file == NULL) {
- ALOGI("Failed to open the file descriptor");
- return NULL;
- }
-
- if (fgets(jpegSignature.get(), kJpegSignatureSize, file) == NULL) {
- ALOGI("Corrupted image.");
- return NULL;
- }
-
- if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) {
- ALOGI("Should be a JPEG stream.");
- return NULL;
- }
-
- // Rewind the file descriptor.
- fseek(file, 0L, SEEK_SET);
-
- std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
- SkFILEStream::kCallerPasses_Ownership));
- return getRawAttributes(env, fileStream.get(), false);
-}
-
-static jobject ExifInterface_getRawAttributesFromInputStream(
- JNIEnv* env, jclass /* clazz */, jobject jinputStream) {
- jbyteArray byteArray = env->NewByteArray(8*1024);
- ScopedLocalRef<jbyteArray> scoper(env, byteArray);
- std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, jinputStream, scoper.get()));
- return getRawAttributes(env, stream.get(), true);
-}
-
-} // extern "C"
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMethods[] = {
- { "nativeInitRaw", "()V", (void *)ExifInterface_initRaw },
- { "nativeGetThumbnailFromAsset", "(JII)[B", (void *)ExifInterface_getThumbnailFromAsset },
- { "nativeGetRawAttributesFromAsset", "(J)Ljava/util/HashMap;",
- (void*)ExifInterface_getRawAttributesFromAsset },
- { "nativeGetRawAttributesFromFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/util/HashMap;",
- (void*)ExifInterface_getRawAttributesFromFileDescriptor },
- { "nativeGetRawAttributesFromInputStream", "(Ljava/io/InputStream;)Ljava/util/HashMap;",
- (void*)ExifInterface_getRawAttributesFromInputStream },
-};
-
-int register_android_media_ExifInterface(JNIEnv *env) {
- return AndroidRuntime::registerNativeMethods(
- env,
- "android/media/ExifInterface",
- gMethods,
- NELEM(gMethods));
-}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2fb1a3b..ecf733f 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1090,7 +1090,6 @@
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
-extern int register_android_media_ExifInterface(JNIEnv *env);
extern int register_android_media_ImageReader(JNIEnv *env);
extern int register_android_media_ImageWriter(JNIEnv *env);
extern int register_android_media_Crypto(JNIEnv *env);
@@ -1222,11 +1221,6 @@
goto bail;
}
- if (register_android_media_ExifInterface(env) < 0) {
- ALOGE("ERROR: ExifInterface native registration failed");
- goto bail;
- }
-
/* success -- return valid version number */
result = JNI_VERSION_1_4;
diff --git a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
index 3c5dd37..8af7de6 100644
--- a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
+++ b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
@@ -90,8 +90,8 @@
<item>0.0040</item>
<item>0.0</item>
<item>442/100</item>
- <item>0/1</item>
- <item>0</item>
+ <item />
+ <item />
<item>1970:01:17</item>
<item>53/1,50/1,423/100</item>
<item>N</item>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index 0cc15451..cdd4065 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -252,6 +252,7 @@
if (stringValue != null) {
stringValue = stringValue.trim();
}
+ stringValue = (stringValue == "") ? null : stringValue;
assertEquals(expectedValue, stringValue);
}
diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index 568d82a..a338165 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kaart is gesluit."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kaart is PUK-geslote."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ontsluit tans SIM-kaart…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Patroon ontsluit."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN ontsluit."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Wagwoord ontsluit."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Patroonarea."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sleep-area."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-area"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-PIN-area"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-PUK-area"</string>
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index 68e9ff3..67fdc32 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ሲም ካርድ ተዘግቷል።"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ሲም ካርድ በፒዩኬ ተዘግቷል።"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ሲም ካርዱን በመክፈት ላይ…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"በስርዓተ-ጥለት መክፈት።"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"በፒን መክፈት።"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"በይለፍ ቃል መክፈት።"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"የስርዓተ-ጥለት አካባቢ።"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"የማንሸራተቻ አካባቢ።"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"የፒን አካባቢ"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"የሲም ፒን አካባቢ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"የሲም PUK አካባቢ"</string>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index 09b78e4..8438699 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"شريحة SIM مؤمّنة."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"شريحة SIM مؤمّنة بكود PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"جارٍ إلغاء تأمين شريحة SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رمز PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"إلغاء القفل باستخدام كلمة المرور."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"منطقة النقش."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"منطقة التمرير."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"منطقة رقم التعريف الشخصي"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"منطقة رقم التعريف الشخصي لبطاقة SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"منطقة PUK لبطاقة SIM"</string>
diff --git a/packages/Keyguard/res/values-az-rAZ/strings.xml b/packages/Keyguard/res/values-az-rAZ/strings.xml
index a8a1155..c7a8091 100644
--- a/packages/Keyguard/res/values-az-rAZ/strings.xml
+++ b/packages/Keyguard/res/values-az-rAZ/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kart kilidlənib."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SİM kart PUK ilə kilidlənib."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SİM kartın kilidi açılır..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kild açma modeli."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin kilid açması."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifrə kilidi."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Model sahəsi."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sürüşdürmə sahəsi."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN sahəsi"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN sahəsi"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK sahəsi"</string>
diff --git a/packages/Keyguard/res/values-b+sr+Latn/strings.xml b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
index 22dc059..570f4bc 100644
--- a/packages/Keyguard/res/values-b+sr+Latn/strings.xml
+++ b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica je zaključana PUK kodom."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Otključavanje šablonom."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast šablona."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast prevlačenja."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblast za PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblast za PIN za SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblast za PUK za SIM"</string>
diff --git a/packages/Keyguard/res/values-be-rBY/strings.xml b/packages/Keyguard/res/values-be-rBY/strings.xml
index ca6a476..f357961 100644
--- a/packages/Keyguard/res/values-be-rBY/strings.xml
+++ b/packages/Keyguard/res/values-be-rBY/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта заблакiраваная."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карта заблакiравана PUK-кодам."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Разблакiраванне SIM-карты..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Узор разблакiроўкі."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код разблакiроўкі."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль разблакiроўкі."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Вобласць узора."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Вобласць слайда."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Поле для PIN-кода"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Поле для PIN-кода SIM-карты"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Поле для PUK-кода SIM-карты"</string>
diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml
index 7eb2dbd..988e97f 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картата е заключена."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картата е заключена с PUK код."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картата се отключва…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отключване с фигура."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отключване с ПИН код."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отключване с парола."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област на фигурата."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област на плъзгане."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Област за ПИН кода"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Област за ПИН кода на SIM картата"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Област за PUK кода на SIM картата"</string>
diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml
index 7a33e21..1a2a8dd 100644
--- a/packages/Keyguard/res/values-bn-rBD/strings.xml
+++ b/packages/Keyguard/res/values-bn-rBD/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"সিম কার্ড লক করা আছে৷"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"সিম কার্ডটি PUK কোড দিয়ে লক করা আছে৷"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"সিম কার্ড আনলক করা হচ্ছে…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"প্যাটার্ন দিয়ে আনলক৷"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"পিন দিয়ে আনলক৷"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"পাসওয়ার্ড দিয়ে আনলক৷"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"প্যাটার্ন এলাকা৷"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"স্লাইড করার এলাকা৷"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"পিন অঞ্চল"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM পিন অঞ্চল"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK অঞ্চল"</string>
diff --git a/packages/Keyguard/res/values-bs-rBA/strings.xml b/packages/Keyguard/res/values-bs-rBA/strings.xml
index 3c3af7b..b8ff2a9 100644
--- a/packages/Keyguard/res/values-bs-rBA/strings.xml
+++ b/packages/Keyguard/res/values-bs-rBA/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica je zaključana PUK kodom."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Otključavanje uzorkom."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje pinom."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Uzorak oblasti."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast za pomjeranje klizača."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Prostor za PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Prostor za SIM PIN"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Prostor za SIM PUK"</string>
diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml
index b542866..9207e0e 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La targeta SIM està bloquejada."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La targeta SIM està bloquejada pel PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"S\'està desbloquejant la targeta SIM..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueig mitjançant PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueig mitjançant contrasenya"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Àrea de patró"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Àrea per lliscar el dit"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona del PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona del PIN de la SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona del PUK de la SIM"</string>
diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml
index b310323..aa7115d 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta je zablokována."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta je zablokována pomocí kódu PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odblokování SIM karty…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odemknutí gestem."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odemknutí kódem PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odemknutí heslem."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast pro zadání bezpečnostního gesta."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast pro přejetí prstem."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblast kódu PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblast kódu PIN SIM karty"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblast kódu PUK SIM karty"</string>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index b46b536..ebea6ee 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet er låst."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kort er låst med PUK-koden."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kortet låses op…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås op med mønster."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås op med pinkode."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås op med adgangskode."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Strygeområde."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Område for pinkoden"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Område for pinkoden til simkortet"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Område for PUK-koden til simkortet"</string>
diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml
index ae731c3..a519ce8 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-Karte ist gesperrt."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-Karte wird entsperrt…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Entsperrung mit Muster"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Entsperrung mit PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Entsperrung mit Passwort"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bereich für Muster"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bereich für Fingerbewegung"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-Bereich"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-PIN-Bereich"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-PUK-Bereich"</string>
diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml
index c54a7fc..d969266 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Η κάρτα SIM είναι κλειδωμένη."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Η κάρτα SIM είναι κλειδωμένη με κωδικό PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ξεκλείδωμα κάρτας SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ξεκλείδωμα μοτίβου."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ξεκλείδωμα κωδικού ασφαλείας"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ξεκλείδωμα κωδικού πρόσβασης."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Περιοχή μοτίβου."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Περιοχή ολίσθησης"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Περιοχή PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Περιοχή PIN SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Περιοχή PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-en-rAU/strings.xml b/packages/Keyguard/res/values-en-rAU/strings.xml
index e885166..9ecd979 100644
--- a/packages/Keyguard/res/values-en-rAU/strings.xml
+++ b/packages/Keyguard/res/values-en-rAU/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string>
diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml
index e885166..9ecd979 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string>
diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml
index e885166..9ecd979 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string>
diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml
index df0db2d..61f5c0d 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La tarjeta SIM está bloqueada."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La tarjeta SIM está bloqueada por código PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarjeta SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslizamiento"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área de PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área de PIN de SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área de PUK de SIM"</string>
diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml
index 6061b78..3ef737c 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La tarjeta SIM está bloqueada."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La tarjeta SIM está bloqueada con el código PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarjeta SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área para deslizar"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área de PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área de PIN de SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área de PUK de SIM"</string>
diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml
index 78ae3ca..47b6332 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kaart on lukus."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kaart on PUK-lukus."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kaardi avamine ..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mustriga avamine."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-koodiga avamine."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parooliga avamine."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mustri ala."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Lohistamisala."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-koodi ala"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-kaardi PIN-koodi ala"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-kaardi PUK-koodi ala"</string>
diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml
index 7855b16..5f4abce 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM txartela blokeatuta dago."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM txartela PUK bidez blokeatuta dago."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM txartela desblokeatzen…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ereduaren bidez desblokeatzea."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN kodearen bidez desblokeatzea."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pasahitzaren bidez desblokeatzea."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eredua marrazteko eremua."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Hatza lerratzeko eremua."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kodearen eremua"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM txartelaren PIN kodearen eremua"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM txartelaren PUK kodearen eremua"</string>
diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml
index 39fd460..40952e2 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"سیم کارت قفل شد."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"سیم کارت با PUK قفل شده است."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"درحال بازگشایی قفل سیم کارت..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"باز کردن قفل با الگو."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"باز کردن قفل با پین."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"باز کردن قفل با گذرواژه."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ناحیه الگو."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ناحیه کشیدن انگشت روی صفحه."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"قسمت پین"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"قسمت پین سیمکارت"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"قسمت PUK سیمکارت"</string>
diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml
index 7a0c00f..a1b96ca 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortti on lukittu."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortti on PUK-lukittu."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kortin lukitusta poistetaan…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lukituksen poisto salasanalla."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lukituksen poisto PIN-koodilla."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lukituksen poisto salasanalla."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kuvioalue."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Liu\'utusalue."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-koodin alue"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-kortin PIN-koodin alue"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-kortin PUK-koodin alue"</string>
diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml
index 9bc2456..d920415 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La carte SIM est verrouillée."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La carte SIM est verrouillée par clé PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Déverrouillage de la carte SIM en cours…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par NIP"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zone du NIP"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zone du NIP de la carte SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zone du code PUK de la carte SIM"</string>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index ecb2575..8615b99 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La carte SIM est verrouillée."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La carte SIM est verrouillée par clé PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Déverrouillage de la carte SIM en cours…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par code PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Champ du code PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Champ du code PIN de la carte SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Champ du code PUK de la carte SIM"</string>
diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml
index 382dd7b..a894fc5 100644
--- a/packages/Keyguard/res/values-gl-rES/strings.xml
+++ b/packages/Keyguard/res/values-gl-rES/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"A tarxeta SIM está bloqueada."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"A tarxeta SIM está bloqueada mediante un PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarxeta SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo mediante padrón"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo mediante PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo mediante contrasinal"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zona do padrón"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zona para pasar o dedo"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN da tarxeta SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK da tarxeta SIM"</string>
diff --git a/packages/Keyguard/res/values-gu-rIN/strings.xml b/packages/Keyguard/res/values-gu-rIN/strings.xml
index eddd1a1..d288b3f 100644
--- a/packages/Keyguard/res/values-gu-rIN/strings.xml
+++ b/packages/Keyguard/res/values-gu-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM કાર્ડ લૉક કરેલ છે."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM કાર્ડ, PUK-લૉક કરેલ છે."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM કાર્ડ અનલૉક કરી રહ્યાં છે…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"પેટર્ન અનલૉક."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"પિન અનલૉક."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"પાસવર્ડ અનલૉક કરો."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"પેટર્ન ક્ષેત્ર."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"સ્લાઇડ ક્ષેત્ર."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ક્ષેત્ર"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ક્ષેત્ર"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ક્ષેત્ર"</string>
diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml
index 8069c5e..bf36312 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक है."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK द्वारा लॉक किया हुआ है."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक हो रहा है…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"आकार अनलॉक."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलॉक."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"आकार क्षेत्र."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पिन क्षेत्र"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"सिम पिन क्षेत्र"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"सिम पिइउके क्षेत्र"</string>
diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml
index 044786d..169bc57 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica zaključana je PUK-om."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Uzorak za otključavanje."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje zaporkom."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Područje uzorka."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Područje klizanja."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Područje PIN-a"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Područje PIN-a za SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Područje PUK-a za SIM"</string>
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index e54a89f..bc3bf4e 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"A SIM kártya le van zárva."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"A SIM kártya le van zárva a PUK kóddal."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM kártya feloldása..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Feloldás mintával"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Feloldás PIN kóddal"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Feloldás jelszóval"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mintaterület"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Csúsztatási terület"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kód területe"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN-kód területe"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK kód területe"</string>
diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml
index 6758a2e..4aacf8f 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM քարտը կողպված է:"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM քարտը PUK-ով կողպված է:"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM քարտը ապակողպվում է..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Սխեմայով ապակողպում:"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin-ն ապակողպված է:"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Գաղտնաբառի ապակողպում:"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Սխեմայի տարածք:"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Սահեցման տարածք:"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN կոդի տարածք"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM քարտի PIN կոդի տարածք"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM քարտի PUK կոդի տարածք"</string>
diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml
index 6f8e7f1..dda63a8 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kartu SIM terkunci."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kartu SIM terkunci PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Membuka kartu SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci dengan pola."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci dengan PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci dengan sandi."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area pola."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area geser."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Bidang PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Bidang PIN SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Bidang PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml
index 279ffcf..278e031 100644
--- a/packages/Keyguard/res/values-is-rIS/strings.xml
+++ b/packages/Keyguard/res/values-is-rIS/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortið er læst."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortið er PUK-læst."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Tekur SIM-kort úr lás…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Opnun með mynstri."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Opnun með PIN-númeri."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Opnun með aðgangsorði."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Svæði mynsturs."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Stroksvæði."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-svæði"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-svæði SIM-korts"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-svæði SIM-korts"</string>
diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml
index 728974d..98bcae4 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La SIM è bloccata."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La SIM è bloccata tramite PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Sblocco scheda SIM..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Sblocco con sequenza."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Sblocco con PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Sblocco con password."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area sequenza."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area di scorrimento."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Area PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Area PIN SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Area PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml
index 47d0728..8d1ada3 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"כרטיס ה-SIM נעול."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"כרטיס SIM נעול באמצעות PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"מבטל נעילה של כרטיס SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ביטול נעילה באמצעות ציור קו."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ביטול נעילה באמצעות מספר PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ביטול נעילה באמצעות סיסמה."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"אזור ציור קו."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"אזור הסטה."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"אזור עבור קוד PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"אזור עבור קוד PIN של SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"אזור עבור קוד PUK של SIM"</string>
diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml
index d30355f..c4b4c98 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIMカードはロックされています。"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIMカードはPUKでロックされています。"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIMカードをロック解除しています…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"パターンロックを解除します。"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PINロックを解除します。"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"パスワードロックを解除します。"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"パターンエリアです。"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"スライドエリアです。"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PINエリア"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PINエリア"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUKエリア"</string>
diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml
index a398e00..658194ff 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM ბარათი დაბლოკილია."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM ბარათი დაბლოკილია PUK კოდით."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"მიმდინარეობს SIM ბარათის განბლოკვა…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"განბლოკვა ნიმუშით."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"განბლოკვა Pin-ით."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"პაროლის განბლოკვა"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ნიმუშების სივრცე."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"გადასრიალების სივრცე."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-ის არე"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-ის PIN-ის არე"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-ის PUK-ის არე"</string>
diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml
index be261fb..2eb3948 100644
--- a/packages/Keyguard/res/values-kk-rKZ/strings.xml
+++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картасы бекітулі."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картасының PUK коды бекітілген."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картасының бекітпесін ашуда…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Кескін арқылы ашу."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin арқылы ашу."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Құпия сөз арқылы ашу."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Кескін арқылы ашу аймағы."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Сырғыту аймағы."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN аумағы"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN аумағы"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK аумағы"</string>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index 4d3f6e8..fce46c7 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ស៊ីមកាតជាប់សោ។"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ស៊ីមកាតជាប់កូដ PUK ។"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"កំពុងដោះសោស៊ីមកាត..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"លំនាំដោះសោ។"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"កូដ PIN ដោះសោ។"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ពាក្យសម្ងាត់ដោះសោ។"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ផ្ទៃលំនាំ។"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ផ្ទៃរុញ។"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ប្រអប់លេខសម្ងាត់"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ប្រអប់លេខសម្ងាត់ស៊ីម"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ប្រអប់ PUK ស៊ីម"</string>
diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml
index 5691a63..7bac9c6 100644
--- a/packages/Keyguard/res/values-kn-rIN/strings.xml
+++ b/packages/Keyguard/res/values-kn-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ನು PUK-ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ಪ್ಯಾಟರ್ನ್ ಅನ್ಲಾಕ್."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ಪಿನ್ ಅನ್ಲಾಕ್."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ಪಾಸ್ವರ್ಡ್ ಅನ್ಲಾಕ್."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ಪ್ಯಾಟರ್ನ್ ಪ್ರದೇಶ."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ಸ್ಲೈಡ್ ಪ್ರದೇಶ."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ಪಿನ್ ಪ್ರದೇಶ"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ಸಿಮ್ ಪಿನ್ ಪ್ರದೇಶ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ಸಿಮ್ PUK ಪ್ರದೇಶ"</string>
diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml
index 2eeef2b..5d40d4d 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 카드가 잠겨 있습니다."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 카드가 PUK 잠김 상태입니다."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM 카드 잠금해제 중..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"패턴을 사용하여 잠금해제합니다."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"핀을 사용하여 잠금해제합니다."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"비밀번호를 사용하여 잠금해제합니다."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"패턴을 그리는 부분입니다."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"슬라이드하는 부분입니다."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 영역"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN 영역"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK 영역"</string>
diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml
index d42b1fa..a485528 100644
--- a/packages/Keyguard/res/values-ky-rKG/strings.xml
+++ b/packages/Keyguard/res/values-ky-rKG/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта бөгөттөлгөн."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карта PUK-бөгөттө."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-карта бөгөттөн чыгарылууда…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Үлгү менен ачуу."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Пин код менен ачуу."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Сырсөз менен ачуу."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Үлгү аймагы."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Жылмыштыруу аймагы."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN аймагы"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN аймагы"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK аймагы"</string>
diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml
index 8e7c813..29a1b56 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ຊິມກາດຖືກລັອກ."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ຊິມກາດຖືກລັອກດ້ວຍລະຫັດ PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ກຳລັງປົດລັອກຊິມກາດ..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ປົດລັອກດ້ວຍຮູບແບບ."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ປົດລັອກດ້ວຍ PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ການປົດລັອກດ້ວຍລະຫັດຜ່ານ."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ພື້ນທີ່ຮູບແບບ."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ເລື່ອນພື້ນທີ່."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ພື້ນທີ່ PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ພື້ນທີ່ PIN ຂອງ SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ພື້ນທີ່ PUK ຂອງ SIM"</string>
diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml
index 653c089..fd41efc 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kortelė užrakinta."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kortelė užrakinta PUK kodu."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Atrakinama SIM kortelė…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Atrakinimas pagal piešinį."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Atrakinimas įvedus PIN kodą."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Atrakinimas įvedus slaptažodį."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Atrakinimo pagal piešinį sritis."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slydimo sritis."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kodo sritis"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM kortelės PIN kodo sritis"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM kortelės PUK kodo sritis"</string>
diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml
index 449659e..f801d64 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karte ir bloķēta."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karte ir bloķēta ar PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Notiek SIM kartes atbloķēšana..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Autorizācija ar kombināciju."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Autorizācija ar PIN kodu."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Autorizācija ar paroli."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kombinācijas ievades apgabals."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Apgabals, kur vilkt ar pirkstu."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN apgabals"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN apgabals"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK apgabals"</string>
diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml
index a6ee921..9d833f0 100644
--- a/packages/Keyguard/res/values-mk-rMK/strings.xml
+++ b/packages/Keyguard/res/values-mk-rMK/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"СИМ картичката е заклучена."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"СИМ картичката е заклучена со ПУК."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"СИМ картичката се отклучува..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отклучување со шема."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отклучување со пин."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отклучување со лозинка."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област за шема."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област за лизгање."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Поле за PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Поле за PIN на СИМ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Поле за ПУК на СИМ"</string>
diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml
index fa39ae1..5d93cf0 100644
--- a/packages/Keyguard/res/values-ml-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ml-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"സിം കാർഡ് ലോക്കുചെയ്തു."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"സിം കാർഡ് PUK-ലോക്ക് ചെയ്തതാണ്."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"സിം കാർഡ് അൺലോക്കുചെയ്യുന്നു…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"പാറ്റേൺ അൺലോക്ക്."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"പിൻ അൺലോക്ക്."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"പാസ്വേഡ് അൺലോക്ക്."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"പാറ്റേൺ ഏരിയ."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"സ്ലൈഡ് ഏരിയ."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ഏരിയ"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ഏരിയ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ഏരിയ"</string>
diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml
index fae0328..8641e31 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM карт түгжигдсэн."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картны PUK-түгжигдсэн."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картны түгжээг гаргаж байна…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Тайлах хээ."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Тайлах пин."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Тайлах нууц үг."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Хээний хэсэг."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Гулсуулах хэсэг."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN талбар"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN талбар"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK талбар"</string>
diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml
index 57a95be..8bcaad6 100644
--- a/packages/Keyguard/res/values-mr-rIN/strings.xml
+++ b/packages/Keyguard/res/values-mr-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक झाले आहे."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK-लॉक केलेले आहे."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक करत आहे…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"नमुना अनलॉक."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"संकेतशब्द अनलॉक."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"नमुना क्षेत्र."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पिन क्षेत्र"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"सिम पिन क्षेत्र"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"सिम PUK क्षेत्र"</string>
diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml
index 803d40a..b7b093f 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kad SIM dikunci."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kad SIM dikunci dengan PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Membuka kunci kad SIM..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci corak."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci pin."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci kata laluan."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kawasan corak."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kawasan luncur."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Kawasan PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Kawasan PIN SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Kawasan PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml
index fd800e4..7a7664e 100644
--- a/packages/Keyguard/res/values-my-rMM/strings.xml
+++ b/packages/Keyguard/res/values-my-rMM/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ဆင်းမ်ကဒ် သော့ကျနေပါသည်"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ဆင်းမ်ကဒ် ရဲ့ ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် သော့ကျနေပါသည်"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ဆင်းမ်ကဒ် ကို သော့ဖွင့်နေပါသည်"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ပုံစံဖြင့် သော့ဖွင့်ခြင်း"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ပင်နံပါတ်ဖြင့် သော့ဖွင့်ခြင်း"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"စကားဝှက်ဖြင့် သော့ဖွင့်ခြင်း"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ပုံစံနေရာ"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ဘေးတိုက်ပွတ်ဆွဲရန် နေရာ"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN နေရာ"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN နေရာ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK နေရာ"</string>
diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml
index 1bdf444..e0035da 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet er låst."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortet er PUK-låst."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Låser opp SIM-kortet ..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mønsteropplåsning."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-opplåsning."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Passordopplåsning."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Dra-felt."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-området"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-området for SIM-kortet"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-området for SIM-kortet"</string>
diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml
index 2cf863d..47f5432 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM कार्ड लक गरियो।"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM कार्ड PUK-लक छ।"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM कार्ड अनलक हुँदै…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ढाँचा अनलक।"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin अनलक"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलक।"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ढाँचा क्षेत्र।"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र।"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पीन क्षेत्र"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM पिन क्षेत्र"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM पुक क्षेत्र"</string>
diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml
index a33165d..c44381e 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Simkaart is vergrendeld."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Simkaart is vergrendeld met PUK-code."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Simkaart ontgrendelen…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ontgrendeling via patroon."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ontgrendeling via pincode."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ontgrendeling via wachtwoord."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Tekengebied voor patroon."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Schuifgebied."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Gebied voor pincode"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Gebied voor sim-pincode"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Gebied voor sim-pukcode"</string>
diff --git a/packages/Keyguard/res/values-pa-rIN/strings.xml b/packages/Keyguard/res/values-pa-rIN/strings.xml
index 8cf86a0..16ca29c 100644
--- a/packages/Keyguard/res/values-pa-rIN/strings.xml
+++ b/packages/Keyguard/res/values-pa-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM ਕਾਰਡ PUK-ਲੌਕਡ ਹੈ।"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ਪੈਟਰਨ ਅਨਲੌਕ।"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin ਅਨਲੌਕ।"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ਪਾਸਵਰਡ ਅਨਲੌਕ।"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ਪੈਟਰਨ ਖੇਤਰ।"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ਖੇਤਰ ਸਲਾਈਡ ਕਰੋ।"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ਖੇਤਰ"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ਖੇਤਰ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ਖੇਤਰ"</string>
diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml
index ee20850..f0980da 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Karta SIM jest zablokowana."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Karta SIM jest zablokowana za pomocą kodu PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odblokowuję kartę SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odblokowanie wzorem."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odblokowanie kodem PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odblokowanie hasłem."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Obszar wzoru."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Obszar przesuwania."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Miejsce na PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Miejsce na PIN do karty SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Miejsce na PUK do karty SIM"</string>
diff --git a/packages/Keyguard/res/values-pt-rBR/strings.xml b/packages/Keyguard/res/values-pt-rBR/strings.xml
index d7215c1..2663337 100644
--- a/packages/Keyguard/res/values-pt-rBR/strings.xml
+++ b/packages/Keyguard/res/values-pt-rBR/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado pelo PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando o cartão SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml
index f0b2bbc..e417e07 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado por PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"A desbloquear o cartão SIM..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio através de sequência."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio através de PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio através de palavra-passe."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área da sequência."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN do SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK do SIM"</string>
diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml
index d7215c1..2663337 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado pelo PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando o cartão SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index b1b142e..09a066a 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Cardul SIM este blocat."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Cardul SIM este blocat cu codul PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Se deblochează cardul SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Deblocare cu model."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Deblocare cu PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Deblocare cu parolă."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zonă model."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonă glisare."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona codului PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona codului PIN al cardului SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona codului PUK al cardului SIM"</string>
diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml
index 264e42c..7466c66 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта заблокирована"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Для разблокировки SIM-карты требуется PUK-код."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Разблокировка SIM-карты…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Графический ключ"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ввода графического ключа"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область слайдера"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-код"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-код SIM-карты"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-код SIM-карты"</string>
diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml
index 607e8ac..5f96e8c 100644
--- a/packages/Keyguard/res/values-si-rLK/strings.xml
+++ b/packages/Keyguard/res/values-si-rLK/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM පත අගුළු දමා ඇත."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM පත PUK අගුළු ලා ඇත."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM පත අගුළු හරිමින්..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"රටා අගුළු ඇරීම."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN අගුළු ඇරීම."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"මුරපද අගුළු ඇරීම."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"රටා ප්රදේශය."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"සර්පණ ප්රදේශය."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN කොටස"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN කොටස"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK කොටස"</string>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 4cbfd51..82a4f1d4 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta je uzamknutá."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta je uzamknutá pomocou kódu PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Prebieha odomykanie SIM karty..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odomknutie vzorom."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odomknutie kódom PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odomknutie heslom."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblasť na zadanie bezpečnostného vzoru."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblasť na prejdenie prstom."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblasť kódu PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblasť kódu PIN SIM karty"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblasť kódu PUK SIM karty"</string>
diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml
index 91083f5..9100bd3 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kartica SIM je zaklenjena."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kartica SIM je zaklenjena s kodo PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odklepanje kartice SIM …"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odklepanje z vzorcem."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odklepanje s kodo PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odklepanje z geslom."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Območje vzorca."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Območje podrsanja."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Območje za kodo PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Območje za kodo PIN za SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Območje za kodo PUK za SIM"</string>
diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml
index 7f4becb..31d31b7 100644
--- a/packages/Keyguard/res/values-sq-rAL/strings.xml
+++ b/packages/Keyguard/res/values-sq-rAL/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Karta SIM është e kyçur."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Karta SIM është e kyçur me PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Po shkyç kartën SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Shkyçje me motiv."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Shkyçje me PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Shkyçja e fjalëkalimit."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zona e motivit."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonën e rrëshqitjes."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona PIN e kartës SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona e PUK-ut të kartës SIM"</string>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index 62614a6..840cae7 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картица је закључана."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картица је закључана PUK кодом."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Откључавање SIM картице…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Откључавање шаблоном."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Откључавање PIN-ом."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Откључавање лозинком."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област шаблона."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област превлачења."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Област за PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Област за PIN за SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Област за PUK за SIM"</string>
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index 378f047..527c8e6 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet är låst."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortet är PUK-låst."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Låser upp SIM-kort …"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås upp med grafiskt lösenord."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås upp med PIN-kod."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås upp med lösenord."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Fält för grafiskt lösenord."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Fält med dragreglage."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Pinkodsområde"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Pinkodsområde för SIM-kort"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-kodsområde för SIM-kort"</string>
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index b570e9f..c2e7ac9 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kadi imefungwa."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kadi imefungwa na PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Inafungua SIM kadi..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kufungua kwa ruwaza."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Kufungua kwa PIN."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Kufungua kwa nenosiri."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eneo la ruwaza."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Eneo la slaidi."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Eneo la PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Eneo la PIN ya SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Eneo la PUK ya SIM"</string>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index 2e3f588..c80ddce 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"சிம் கார்டு PUK ஆல் பூட்டப்பட்டது."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"வடிவம் மூலம் திறத்தல்."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin மூலம் திறத்தல்."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"கடவுச்சொல் மூலம் திறத்தல்."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"வடிவப் பகுதி."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ஸ்லைடு பகுதி."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN பகுதி"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"சிம் PIN பகுதி"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"சிம் PUK பகுதி"</string>
diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml
index 6c521aa..a72a85b 100644
--- a/packages/Keyguard/res/values-te-rIN/strings.xml
+++ b/packages/Keyguard/res/values-te-rIN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"సిమ్ కార్డు లాక్ చేయబడింది."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"సిమ్ కార్డు PUK లాక్ చేయబడింది."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"సిమ్ కార్డును అన్లాక్ చేస్తోంది…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"నమూనా అన్లాక్."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"పిన్ అన్లాక్."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"పాస్వర్డ్ అన్లాక్."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"నమూనా ప్రాంతం."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"స్లయిడ్ ప్రాంతం."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ప్రాంతం"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ప్రాంతం"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ప్రాంతం"</string>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index 1799fe8..e094d35 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ซิมการ์ดถูกล็อก"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ซิมการ์ดถูกล็อกด้วย PUK"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"กำลังปลดล็อกซิมการ์ด…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"การปลดล็อกด้วยรูปแบบ"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"การปลดล็อกด้วย PIN"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"การปลดล็อกด้วยรหัสผ่าน"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"พื้นที่สำหรับรูปแบบ"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"พื้นที่สำหรับการเลื่อน"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"พื้นที่ PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"พื้นที่ PIN ของซิม"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"พื้นที่ PUK ของซิม"</string>
diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml
index 39cad72..73492e2 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Naka-lock ang SIM card."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Naka-lock ang SIM card gamit ang PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ina-unlock ang SIM card…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pag-unlock ng pattern."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pag-unlock ng pin."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pag-unlock ng password."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bahagi ng pattern."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bahagi ng slide."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Lugar ng PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Lugar ng PIN ng SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Lugar ng PUK ng SIM"</string>
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index ffcbd12..3ef0705 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kart kilitli."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kart PUK kilidi devrede."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM kart kilidi açılıyor…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desenle kilit açma."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin koduyla kilit açma."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifreyle kilit açma."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Desen alanı."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kaydırma alanı."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN alanı"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN alanı"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK alanı"</string>
diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml
index be19281..a508689 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карту заблоковано."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карту заблоковано PUK-кодом."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Розблокування SIM-карти…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Розблокування ключем."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Розблокування PIN-кодом."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Розблокування паролем."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ключа."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область повзунка."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-код"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-код SIM-карти"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-код SIM-карти"</string>
diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml
index 63f4e85..1070d58 100644
--- a/packages/Keyguard/res/values-ur-rPK/strings.xml
+++ b/packages/Keyguard/res/values-ur-rPK/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM کارڈ مقفل ہے۔"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM کارڈ PUK-مقفل ہے۔"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM کارڈ غیر مقفل کیا جا رہا ہے…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"پیٹرن کے ذریعے غیر مقفل کریں۔"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"پن کے ذریعے غیر مقفل کریں۔"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"پاس ورڈ کے ذریعہ غیر مقفل کریں۔"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"پیٹرن کا علاقہ۔"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"سلائیڈ کرنے کا علاقہ۔"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN کا علاقہ"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN کا علاقہ"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK کا علاقہ"</string>
diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml
index ad71a56..a9df331 100644
--- a/packages/Keyguard/res/values-uz-rUZ/strings.xml
+++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta qulflangan."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta PUK kod bilan qulflangan."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM karta qulfi ochilmoqda…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Grafik kalit bilan ochish."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin qulfini ochish."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parolli qulfni ochish."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Grafik kalit chiziladigan hudud."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Maydonni silang"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kod maydoni"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM karta PIN kodi maydoni"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM karta PUK kodi maydoni"</string>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index ad3da9f..c6d2bd8 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Thẻ SIM đã bị khóa."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Thẻ SIM đã bị khóa PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Đang mở khóa thẻ SIM…"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mở khóa bằng hình."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Mở khóa bằng mã pin."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Mở khóa bằng mật khẩu."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Khu vực hình."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Khu vực trượt."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Khu vực mã PIN"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Khu vực mã PIN của SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Khu vực PUK của SIM"</string>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 274d9e6..0723ab1 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM卡已被锁定。"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM卡已被PUK码锁定。"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解锁SIM卡..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"图案解锁。"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN码解锁。"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密码解锁。"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"图案区域。"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑动区域。"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 码区域"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM 卡 PIN 码区域"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM 卡 PUK 码区域"</string>
diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml
index 7d51154..5b1903b 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 卡處於鎖定狀態。"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 卡處於 PUK 鎖定狀態。"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解開上鎖的 SIM 卡..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖案解鎖。"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖案區域。"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 區域"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN 區域"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK 區域"</string>
diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml
index 50895f3..388f8e1 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 卡處於鎖定狀態。"</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 卡處於 PUK 鎖定狀態"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解除 SIM 卡鎖定..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖案解鎖。"</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖案區域。"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 區"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM 卡 PIN 區"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM 卡 PUK 區"</string>
diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml
index c5f2a85..a9b6263 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -46,11 +46,6 @@
<string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Ikhadi le-SIM likhiyiwe."</string>
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Ikhadi le-SIM likhiywe nge-PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ivula ikhadi le-SIM..."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ukuvula ngephethini."</string>
- <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ukuvula ngephinikhodi."</string>
- <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ukuvula ngephasiwedi."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Indawo yephethini."</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Indawo yokushelelisa."</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Indawo yephinikhodi"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Indawo yephinikhodi ye-SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Indawo ye-SIM PUK"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index b75f529..ddccc14 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -42,16 +42,21 @@
* Displays an alphanumeric (latin-1) key entry for the user to enter
* an unlock password
*/
-
public class KeyguardPasswordView extends KeyguardAbsKeyInputView
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private final boolean mShowImeAtScreenOn;
private final int mDisappearYTranslation;
+ // A delay constant to be used in a workaround for the situation where InputMethodManagerService
+ // is not switched to the new user yet.
+ // TODO: Remove this by ensuring such a race condition never happens.
+ private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500; // 500ms
+
InputMethodManager mImm;
private TextView mPasswordEntry;
private TextViewInputDisabler mPasswordEntryDisabler;
+ private View mSwitchImeButton;
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
@@ -141,12 +146,31 @@
mPasswordEntry.requestFocus();
}
+ private void updateSwitchImeButton() {
+ // If there's more than one IME, enable the IME switcher button
+ final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE;
+ final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(mImm, false);
+ if (wasVisible != shouldBeVisible) {
+ mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE);
+ }
+
+ // TODO: Check if we still need this hack.
+ // If no icon is visible, reset the start margin on the password field so the text is
+ // still centered.
+ if (mSwitchImeButton.getVisibility() != View.VISIBLE) {
+ android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+ if (params instanceof MarginLayoutParams) {
+ final MarginLayoutParams mlp = (MarginLayoutParams) params;
+ mlp.setMarginStart(0);
+ mPasswordEntry.setLayoutParams(params);
+ }
+ }
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- boolean imeOrDeleteButtonVisible = false;
-
mImm = (InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
@@ -171,31 +195,29 @@
mPasswordEntry.requestFocus();
- // If there's more than one IME, enable the IME switcher button
- View switchImeButton = findViewById(R.id.switch_ime_button);
- if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) {
- switchImeButton.setVisibility(View.VISIBLE);
- imeOrDeleteButtonVisible = true;
- switchImeButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCallback.userActivity(); // Leave the screen on a bit longer
- // Do not show auxiliary subtypes in password lock screen.
- mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
- }
- });
- }
-
- // If no icon is visible, reset the start margin on the password field so the text is
- // still centered.
- if (!imeOrDeleteButtonVisible) {
- android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- final MarginLayoutParams mlp = (MarginLayoutParams) params;
- mlp.setMarginStart(0);
- mPasswordEntry.setLayoutParams(params);
+ mSwitchImeButton = findViewById(R.id.switch_ime_button);
+ mSwitchImeButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCallback.userActivity(); // Leave the screen on a bit longer
+ // Do not show auxiliary subtypes in password lock screen.
+ mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
}
- }
+ });
+
+ // If there's more than one IME, enable the IME switcher button
+ updateSwitchImeButton();
+
+ // When we the current user is switching, InputMethodManagerService sometimes has not
+ // switched internal state yet here. As a quick workaround, we check the keyboard state
+ // again.
+ // TODO: Remove this workaround by ensuring such a race condition never happens.
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ updateSwitchImeButton();
+ }
+ }, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
}
@Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index aa74940..8290842 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -49,11 +49,6 @@
int PROMPT_REASON_AFTER_LOCKOUT = 5;
/**
- * Some auth is required because a single wrong credential has been tried.
- */
- int PROMPT_REASON_WRONG_CREDENTIAL = 6;
-
- /**
* Interface back to keyguard to tell it when security
* @param callback
*/
diff --git a/packages/SettingsLib/res/values-ky-rKG/arrays.xml b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
index a06ecfb..1aadb9b 100644
--- a/packages/SettingsLib/res/values-ky-rKG/arrays.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
@@ -147,7 +147,7 @@
<string-array name="track_frame_time_entries">
<item msgid="2193584639058893150">"Өчүк"</item>
<item msgid="2751513398307949636">"Экранда тилке катары"</item>
- <item msgid="2355151170975410323">"Төмөнкүдө <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
+ <item msgid="2355151170975410323">"Төмөнкүдө: <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
</string-array>
<string-array name="debug_hw_overdraw_entries">
<item msgid="8190572633763871652">"Өчүк"</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3838143..3bdb6fb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -863,4 +863,7 @@
<!-- Label for Help and feedback menu item -->
<string name="help_feedback_label">Help & feedback</string>
+ <!-- Content description for drawer menu button [CHAR_LIMIT=30]-->
+ <string name="content_description_menu_button">Menu</string>
+
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index cf08f50..687b3fc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -167,7 +167,7 @@
return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
}
- public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
+ private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) {
final NetworkPolicy policy = getOrCreatePolicy(template);
policy.warningBytes = warningBytes;
policy.inferred = false;
@@ -175,12 +175,28 @@
writeAsync();
}
+ public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
+ long limitBytes = getPolicyLimitBytes(template);
+
+ // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes
+ warningBytes = Math.min(warningBytes, limitBytes);
+ setPolicyWarningBytesInner(template, warningBytes);
+ }
+
public long getPolicyLimitBytes(NetworkTemplate template) {
final NetworkPolicy policy = getPolicy(template);
return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
}
+
public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
+ long warningBytes = getPolicyWarningBytes(template);
+
+ // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes
+ if (warningBytes > limitBytes) {
+ setPolicyWarningBytesInner(template, limitBytes);
+ }
+
final NetworkPolicy policy = getOrCreatePolicy(template);
policy.limitBytes = limitBytes;
policy.inferred = false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 6658c14..a50b366 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -226,6 +226,7 @@
public void showMenuIcon() {
mShowingMenu = true;
getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
+ getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index f0c19dc..a1cf3ea 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -40,5 +40,5 @@
<string name="bugreport_info_title" msgid="2306030793918239804">"Tajuk pepijat"</string>
<string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan pepijat"</string>
<string name="save" msgid="4781509040564835759">"Simpan"</string>
- <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Kongsi Laporan pepijat?"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Kongsi Laporan pepijat"</string>
</resources>
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index 1e0eaac..872eb7a 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -8,7 +8,9 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ ub-uiautomator \
LOCAL_PACKAGE_NAME := ShellTests
LOCAL_INSTRUMENTATION_FOR := Shell
diff --git a/packages/Shell/tests/AndroidManifest.xml b/packages/Shell/tests/AndroidManifest.xml
index 54b0802..6d564c6 100644
--- a/packages/Shell/tests/AndroidManifest.xml
+++ b/packages/Shell/tests/AndroidManifest.xml
@@ -36,7 +36,7 @@
</activity>
</application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.shell"
android:label="Tests for Shell" />
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 902c71d..dde71eb 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -36,6 +36,13 @@
import static com.android.shell.BugreportProgressService.POLLING_FREQUENCY;
import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
+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;
+import static org.junit.Assert.fail;
+
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
@@ -56,6 +63,13 @@
import libcore.io.Streams;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.Instrumentation;
@@ -68,11 +82,12 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
@@ -96,7 +111,8 @@
* <strong>NOTE</strong>: these tests only work if the device is unlocked.
*/
@LargeTest
-public class BugreportReceiverTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BugreportReceiverTest {
private static final String TAG = "BugreportReceiverTest";
// Timeout for UI operations, in milliseconds.
@@ -149,9 +165,10 @@
private UiBot mUiBot;
private CustomActionSendMultipleListener mListener;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Rule public TestName mName = new TestName();
+
+ @Before
+ public void setUp() throws Exception {
Log.i(TAG, getName() + ".setup()");
Instrumentation instrumentation = getInstrumentation();
mContext = instrumentation.getTargetContext();
@@ -181,13 +198,13 @@
mUiBot.turnScreenOn();
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
Log.i(TAG, getName() + ".tearDown()");
cancelExistingNotifications();
- super.tearDown();
}
+ @Test
public void testProgress() throws Exception {
resetProperties();
sendBugreportStarted(1000);
@@ -233,6 +250,7 @@
assertServiceNotRunning();
}
+ @Test
public void testProgress_cancel() throws Exception {
resetProperties();
sendBugreportStarted(1000);
@@ -249,6 +267,7 @@
waitForService(false);
}
+ @Test
public void testProgress_takeExtraScreenshot() throws Exception {
resetProperties();
sendBugreportStarted(1000);
@@ -267,6 +286,7 @@
assertServiceNotRunning();
}
+ @Test
public void testScreenshotFinishesAfterBugreport() throws Exception {
resetProperties();
@@ -286,6 +306,7 @@
assertServiceNotRunning();
}
+ @Test
public void testProgress_changeDetailsInvalidInput() throws Exception {
resetProperties();
sendBugreportStarted(1000);
@@ -331,6 +352,7 @@
assertServiceNotRunning();
}
+ @Test
public void testProgress_cancelBugClosesDetailsDialog() throws Exception {
resetProperties();
sendBugreportStarted(1000);
@@ -346,10 +368,12 @@
assertServiceNotRunning();
}
+ @Test
public void testProgress_changeDetailsPlainBugreport() throws Exception {
changeDetailsTest(true);
}
+ @Test
public void testProgress_changeDetailsZippedBugreport() throws Exception {
changeDetailsTest(false);
}
@@ -383,10 +407,12 @@
assertServiceNotRunning();
}
+ @Test
public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
changeJustDetailsTest(true);
}
+ @Test
public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
changeJustDetailsTest(false);
}
@@ -410,6 +436,7 @@
assertServiceNotRunning();
}
+ @Test
public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
resetProperties();
sendBugreportStarted(ID, PID, NAME, 1000);
@@ -453,6 +480,7 @@
* Tests the scenario where the initial screenshot and dumpstate are finished while the user
* is changing the info in the details screen.
*/
+ @Test
public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
bugreportFinishedWhileChangingDetailsTest(false);
}
@@ -461,6 +489,7 @@
* Tests the scenario where dumpstate is finished while the user is changing the info in the
* details screen, but the initial screenshot finishes afterwards.
*/
+ @Test
public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
bugreportFinishedWhileChangingDetailsTest(true);
}
@@ -500,14 +529,17 @@
assertServiceNotRunning();
}
+ @Test
public void testBugreportFinished_withWarningFirstTime() throws Exception {
bugreportFinishedWithWarningTest(null);
}
+ @Test
public void testBugreportFinished_withWarningUnknownState() throws Exception {
bugreportFinishedWithWarningTest(STATE_UNKNOWN);
}
+ @Test
public void testBugreportFinished_withWarningShowAgain() throws Exception {
bugreportFinishedWithWarningTest(STATE_SHOW);
}
@@ -560,6 +592,7 @@
assertEquals("Didn't change state", STATE_HIDE, newState);
}
+ @Test
public void testShareBugreportAfterServiceDies() throws Exception {
sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
waitForService(false);
@@ -567,21 +600,25 @@
assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
}
+ @Test
public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
}
+ @Test
public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
}
+ @Test
public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
}
+ @Test
public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
@@ -1001,6 +1038,14 @@
mUiBot.assertNotVisibleById("android:id/alertTitle");
}
+ private String getName() {
+ return mName.getMethodName();
+ }
+
+ private Instrumentation getInstrumentation() {
+ return InstrumentationRegistry.getInstrumentation();
+ }
+
private static void sleep(long ms) {
Log.d(TAG, "sleeping for " + ms + "ms");
SystemClock.sleep(ms);
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index 0a2f320..49119fb 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -41,5 +41,6 @@
android:layout_height="wrap_content"
android:layout_marginStart="-50dp"
android:src="@drawable/ic_pause_white_24dp"
- android:text="@string/pip_pause" />
+ android:text="@string/pip_pause"
+ android:visibility="gone" />
</merge>
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index ea26bba..775b157 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -18,7 +18,8 @@
android:id="@+id/volume_zen_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical" > <!-- extends LinearLayout -->
+ android:orientation="vertical"
+ android:paddingBottom="8dp" > <!-- extends LinearLayout -->
<View
android:id="@+id/zen_embedded_divider"
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4893598..fe27459 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -602,7 +602,7 @@
<string name="keycode_description" msgid="1403795192716828949">"Näppäinkoodi-painikkeet sallivat näppäimistön näppäimien lisäämisen navigointipalkkiin. Kun painiketta painetaan, se jäljittelee valittua näppäintä. Valitse ensin painikkeen kohteena oleva näppäin, sitten painikkeessa näkyvä kuva."</string>
<string name="select_keycode" msgid="7413765103381924584">"Valitse näppäimistön näppäin"</string>
<string name="preview" msgid="9077832302472282938">"Esikatselu"</string>
- <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä."</string>
+ <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Poista vetämällä tähän."</string>
<string name="qs_edit" msgid="2232596095725105230">"Muokkaa"</string>
<string name="tuner_time" msgid="6572217313285536011">"Aika"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5acc177..a93c3e2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -313,7 +313,7 @@
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Données mobiles"</string>
- <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Consommation des données"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Conso des données"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
<string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite dépassée"</string>
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilisés"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index de96cb0..a15ba26 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -309,7 +309,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
- <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn nháy"</string>
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dữ liệu di động"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8b592c2..c4ef80f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -86,7 +86,6 @@
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -626,10 +625,7 @@
return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
- } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL) != 0) {
- return KeyguardSecurityView.PROMPT_REASON_WRONG_CREDENTIAL;
}
-
return KeyguardSecurityView.PROMPT_REASON_NONE;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index ac90ce7..19a5d52 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -237,6 +237,10 @@
mQSPanel.setListening(mListening && mQsExpanded);
}
+ public void setHeaderListening(boolean listening) {
+ mHeader.setListening(listening);
+ }
+
public void setQsExpansion(float expansion, float headerTranslation) {
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
mQsExpansion = expansion;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b6597a0..ed0fc1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -251,10 +251,12 @@
if (mListening) {
refreshAllTiles();
}
- if (listening) {
- mBrightnessController.registerCallbacks();
- } else {
- mBrightnessController.unregisterCallbacks();
+ if (mBrightnessView.getVisibility() == View.VISIBLE) {
+ if (listening) {
+ mBrightnessController.registerCallbacks();
+ } else {
+ mBrightnessController.unregisterCallbacks();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 4638c85..1343c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -26,6 +26,7 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
+import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableWrapper;
@@ -224,6 +225,12 @@
}
@Override
+ public void setXfermode(@Nullable Xfermode mode) {
+ // DrawableWrapper does not call this for us.
+ getDrawable().setXfermode(mode);
+ }
+
+ @Override
public int getIntrinsicWidth() {
return -1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f27f8f5..812c5c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1617,6 +1617,9 @@
if (mQsExpanded) {
onQsExpansionStarted();
}
+ // Since there are QS tiles in the header now, we need to make sure we start listening
+ // immediately so they can be up to date.
+ mQsContainer.setHeaderListening(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index c9cde9d..047085d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -501,7 +501,7 @@
mMotion.startDismiss(new Runnable() {
@Override
public void run() {
- updateExpandedH(false);
+ updateExpandedH(false /* expanding */, true /* dismissing */);
}
});
if (mAccessibilityMgr.isEnabled()) {
@@ -547,45 +547,47 @@
mHandler.sendEmptyMessageDelayed(H.UPDATE_BOTTOM_MARGIN, getConservativeCollapseDuration());
}
- private void updateExpandedH(final boolean expanded) {
+ private void updateExpandedH(final boolean expanded, final boolean dismissing) {
if (mExpanded == expanded) return;
mExpanded = expanded;
mExpandButtonAnimationRunning = isAttached();
if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded);
updateExpandButtonH();
updateFooterH();
- final VolumeRow activeRow = getActiveRow();
- mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
- AutoTransition transition = new AutoTransition();
- transition.setDuration(mExpandButtonAnimationDuration);
- transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- transition.addListener(new Transition.TransitionListener() {
- @Override
- public void onTransitionStart(Transition transition) {
- }
-
- @Override
- public void onTransitionEnd(Transition transition) {
- mWindow.setLayout(
- mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- @Override
- public void onTransitionCancel(Transition transition) {
- mWindow.setLayout(
- mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- @Override
- public void onTransitionPause(Transition transition) {
- }
-
- @Override
- public void onTransitionResume(Transition transition) {
- }
- });
TransitionManager.endTransitions(mDialogView);
- TransitionManager.beginDelayedTransition(mDialogView, transition);
+ final VolumeRow activeRow = getActiveRow();
+ if (!dismissing) {
+ mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
+ AutoTransition transition = new AutoTransition();
+ transition.setDuration(mExpandButtonAnimationDuration);
+ transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ transition.addListener(new Transition.TransitionListener() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mWindow.setLayout(
+ mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ mWindow.setLayout(
+ mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ }
+ });
+ TransitionManager.beginDelayedTransition(mDialogView, transition);
+ }
updateRowsH(activeRow);
rescheduleTimeoutH();
}
@@ -1035,7 +1037,7 @@
if (mExpandButtonAnimationRunning) return;
final boolean newExpand = !mExpanded;
Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
- updateExpandedH(newExpand);
+ updateExpandedH(newExpand, false /* dismissing */);
}
};
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 82b3050..242eca8 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -34,6 +34,8 @@
import android.util.Slog;
import android.util.Xml;
+import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParser;
import java.io.File;
@@ -112,56 +114,58 @@
touch.close();
fullBackupFile(empty, data);
- // only back up the wallpaper if we've been told it's allowed
- if (mWm.isWallpaperBackupEligible()) {
- if (DEBUG) {
- Slog.v(TAG, "Wallpaper is backup-eligible");
- }
+ SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+ final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
+ final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
- SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
- final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
- final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
+ final int sysGeneration =
+ mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
+ final int lockGeneration =
+ mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
+ final boolean sysChanged = (sysGeneration != lastSysGeneration);
+ final boolean lockChanged = (lockGeneration != lastLockGeneration);
- final int sysGeneration =
- mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
- final int lockGeneration =
- mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
- final boolean sysChanged = (sysGeneration != lastSysGeneration);
- final boolean lockChanged = (lockGeneration != lastLockGeneration);
+ final boolean sysEligible = mWm.isWallpaperBackupEligible(FLAG_SYSTEM);
+ final boolean lockEligible = mWm.isWallpaperBackupEligible(FLAG_LOCK);
- if (DEBUG) {
- Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
- Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
- }
- if (mWallpaperInfo.exists()) {
- if (sysChanged || lockChanged || !infoStage.exists()) {
- if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
- FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
- }
- fullBackupFile(infoStage, data);
- }
- if (mWallpaperFile.exists()) {
- if (sysChanged || !imageStage.exists()) {
- if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
- FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
- }
- fullBackupFile(imageStage, data);
- prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
- }
+ // There might be a latent lock wallpaper file present but unused: don't
+ // include it in the backup if that's the case.
+ ParcelFileDescriptor lockFd = mWm.getWallpaperFile(FLAG_LOCK, UserHandle.USER_SYSTEM);
+ final boolean hasLockWallpaper = (lockFd != null);
+ IoUtils.closeQuietly(lockFd);
- // Don't try to store the lock image if we overran our quota last time
- if (mLockWallpaperFile.exists() && !mQuotaExceeded) {
- if (lockChanged || !lockImageStage.exists()) {
- if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
- FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
- }
- fullBackupFile(lockImageStage, data);
- prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
+ if (DEBUG) {
+ Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
+ Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
+ Slog.v(TAG, "sysEligble=" + sysEligible);
+ Slog.v(TAG, "lockEligible=" + lockEligible);
+ }
+
+ // only back up the wallpapers if we've been told they're eligible
+ if ((sysEligible || lockEligible) && mWallpaperInfo.exists()) {
+ if (sysChanged || lockChanged || !infoStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
+ FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
}
- } else {
- if (DEBUG) {
- Slog.v(TAG, "Wallpaper not backup-eligible; writing no data");
+ fullBackupFile(infoStage, data);
+ }
+ if (sysEligible && mWallpaperFile.exists()) {
+ if (sysChanged || !imageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
+ FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
}
+ fullBackupFile(imageStage, data);
+ prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
+ }
+
+ // Don't try to store the lock image if we overran our quota last time
+ if (lockEligible && hasLockWallpaper && mLockWallpaperFile.exists() && !mQuotaExceeded) {
+ if (lockChanged || !lockImageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
+ FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
+ }
+ fullBackupFile(lockImageStage, data);
+ prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
}
} catch (Exception e) {
Slog.e(TAG, "Unable to back up wallpaper", e);
@@ -199,15 +203,20 @@
final File imageStage = new File (filesDir, IMAGE_STAGE);
final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
+ // If we restored separate lock imagery, the system wallpaper should be
+ // applied as system-only; but if there's no separate lock image, make
+ // sure to apply the restored system wallpaper as both.
+ final int sysWhich = FLAG_SYSTEM | (lockImageStage.exists() ? 0 : FLAG_LOCK);
+
try {
// First off, revert to the factory state
- mWm.clear(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+ mWm.clear(FLAG_SYSTEM | FLAG_LOCK);
// It is valid for the imagery to be absent; it means that we were not permitted
// to back up the original image on the source device, or there was no user-supplied
// wallpaper image present.
- restoreFromStage(imageStage, infoStage, "wp", WallpaperManager.FLAG_SYSTEM);
- restoreFromStage(lockImageStage, infoStage, "kwp", WallpaperManager.FLAG_LOCK);
+ restoreFromStage(imageStage, infoStage, "wp", sysWhich);
+ restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK);
} catch (Exception e) {
Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
} finally {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 983a656..ea25f74 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -21,6 +21,7 @@
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.GestureDescription;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
@@ -2787,7 +2788,7 @@
}
@Override
- public void sendMotionEvents(int sequence, ParceledListSlice events) {
+ public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
synchronized (mLock) {
if (mSecurityPolicy.canPerformGestures(this)) {
final long endMillis =
@@ -2801,9 +2802,16 @@
}
}
if (mMotionEventInjector != null) {
- mMotionEventInjector.injectEvents((List<MotionEvent>) events.getList(),
- mServiceInterface, sequence);
- return;
+ List<GestureDescription.GestureStep> steps = gestureSteps.getList();
+ List<MotionEvent> events = GestureDescription.MotionEventGenerator
+ .getMotionEventsFromGestureSteps(steps);
+ // Confirm that the motion events end with an UP event.
+ if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
+ mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
+ return;
+ } else {
+ Slog.e(LOG_TAG, "Gesture is not well-formed");
+ }
} else {
Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 915d839..9cc53f0 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -34,6 +34,7 @@
@Override
public void onStart() {
+ mImpl.onStart();
publishBinderService(Context.APPWIDGET_SERVICE, mImpl);
AppWidgetBackupBridge.register(mImpl);
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 47094be..5ec3f2b 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -201,21 +201,21 @@
private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
- private final BackupRestoreController mBackupRestoreController;
+ private BackupRestoreController mBackupRestoreController;
private final Context mContext;
- private final IPackageManager mPackageManager;
- private final AlarmManager mAlarmManager;
- private final UserManager mUserManager;
- private final AppOpsManager mAppOpsManager;
- private final KeyguardManager mKeyguardManager;
- private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
+ private IPackageManager mPackageManager;
+ private AlarmManager mAlarmManager;
+ private UserManager mUserManager;
+ private AppOpsManager mAppOpsManager;
+ private KeyguardManager mKeyguardManager;
+ private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
- private final SecurityPolicy mSecurityPolicy;
+ private SecurityPolicy mSecurityPolicy;
- private final Handler mSaveStateHandler;
- private final Handler mCallbackHandler;
+ private Handler mSaveStateHandler;
+ private Handler mCallbackHandler;
private Locale mLocale;
@@ -224,10 +224,13 @@
private boolean mSafeMode;
private int mMaxWidgetBitmapMemory;
- private final IconUtilities mIconUtilities;
+ private IconUtilities mIconUtilities;
AppWidgetServiceImpl(Context context) {
mContext = context;
+ }
+
+ public void onStart() {
mPackageManager = AppGlobals.getPackageManager();
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -238,7 +241,7 @@
mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
mBackupRestoreController = new BackupRestoreController();
mSecurityPolicy = new SecurityPolicy();
- mIconUtilities = new IconUtilities(context);
+ mIconUtilities = new IconUtilities(mContext);
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 0316093..20cca16 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2699,7 +2699,7 @@
public void scheduleDateChangedEvent() {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
- calendar.set(Calendar.HOUR, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 488f0e7..6b73fec 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,7 +49,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
-import android.os.IBinder;
import android.os.IDeviceIdleController;
import android.os.IMaintenanceActivityListener;
import android.os.Looper;
@@ -1238,7 +1237,7 @@
}
}
- public final class LocalService {
+ public class LocalService {
public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
String reason) {
addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 2de09a3..801a436 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -52,6 +52,7 @@
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.os.ServiceManager;
+import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -1367,6 +1368,10 @@
return VerifyCredentialResponse.ERROR;
}
+ // We're potentially going to be doing a bunch of disk I/O below as part
+ // of unlocking the user, so yell if calling from the main thread.
+ StrictMode.noteDiskRead();
+
if (storedHash.version == CredentialHash.VERSION_LEGACY) {
byte[] hash = credentialUtil.toHash(credential, userId);
if (Arrays.equals(hash, storedHash.hash)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0ffc35b..09a3a17 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2341,7 +2341,7 @@
Process.SCHED_OTHER, 0);
}
} catch (IllegalArgumentException e) {
- Slog.e(TAG, "Failed to set scheduling policy, thread does"
+ Slog.w(TAG, "Failed to set scheduling policy, thread does"
+ " not exist:\n" + e);
}
}
@@ -3807,6 +3807,15 @@
app.killedByAm = false;
checkTime(startTime, "startProcess: starting to update pids map");
synchronized (mPidsSelfLocked) {
+ ProcessRecord oldApp;
+ // If there is already an app occupying that pid that hasn't been cleaned up
+ if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) {
+ // Clean up anything relating to this pid first
+ Slog.w(TAG, "Reusing pid " + startResult.pid
+ + " while app is still mapped to it");
+ cleanUpApplicationRecordLocked(oldApp, false, false, -1,
+ true /*replacingPid*/);
+ }
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -5039,7 +5048,8 @@
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
- boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
+ boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
+ false /*replacingPid*/);
if (!kept && !restarting) {
removeLruProcessLocked(app);
if (pid > 0) {
@@ -12572,10 +12582,15 @@
proc.vrThreadTid = tid;
// promote to FIFO now if the tid is non-zero
- if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP
- && proc.vrThreadTid > 0) {
- Process.setThreadScheduler(proc.vrThreadTid,
+ try {
+ if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
+ proc.vrThreadTid > 0) {
+ Process.setThreadScheduler(proc.vrThreadTid,
Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ }
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Failed to set scheduling policy, thread does"
+ + " not exist:\n" + e);
}
}
}
@@ -16811,7 +16826,8 @@
* app that was passed in must remain on the process lists.
*/
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
- boolean restarting, boolean allowRestart, int index) {
+ boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
+ Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid);
if (index >= 0) {
removeLruProcessLocked(app);
ProcessList.remove(app.pid);
@@ -16942,7 +16958,9 @@
if (!app.persistent || app.isolated) {
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
- removeProcessNameLocked(app.processName, app.uid);
+ if (!replacingPid) {
+ removeProcessNameLocked(app.processName, app.uid);
+ }
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
mHeavyWeightProcess.userId, 0));
@@ -20350,17 +20368,29 @@
if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
// Switch VR thread for app to SCHED_FIFO
if (mInVrMode && app.vrThreadTid != 0) {
- Process.setThreadScheduler(app.vrThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ try {
+ Process.setThreadScheduler(app.vrThreadTid,
+ Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ } catch (IllegalArgumentException e) {
+ // thread died, ignore
+ }
}
if (mUseFifoUiScheduling) {
// Switch UI pipeline for app to SCHED_FIFO
app.savedPriority = Process.getThreadPriority(app.pid);
- Process.setThreadScheduler(app.pid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
- if (app.renderThreadTid != 0) {
- Process.setThreadScheduler(app.renderThreadTid,
+ try {
+ Process.setThreadScheduler(app.pid,
Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ } catch (IllegalArgumentException e) {
+ // thread died, ignore
+ }
+ if (app.renderThreadTid != 0) {
+ try {
+ Process.setThreadScheduler(app.renderThreadTid,
+ Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ } catch (IllegalArgumentException e) {
+ // thread died, ignore
+ }
if (DEBUG_OOM_ADJ) {
Slog.d("UI_FIFO", "Set RenderThread (TID " +
app.renderThreadTid + ") to FIFO");
@@ -20374,7 +20404,11 @@
// Boost priority for top app UI and render threads
Process.setThreadPriority(app.pid, -10);
if (app.renderThreadTid != 0) {
- Process.setThreadPriority(app.renderThreadTid, -10);
+ try {
+ Process.setThreadPriority(app.renderThreadTid, -10);
+ } catch (IllegalArgumentException e) {
+ // thread died, ignore
+ }
}
}
}
@@ -21258,7 +21292,7 @@
// Ignore exceptions.
}
}
- cleanUpApplicationRecordLocked(app, false, true, -1);
+ cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
mRemovedProcesses.remove(i);
if (app.persistent) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index d02fbbf..219e095 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -304,6 +304,11 @@
boolean didSomething = false;
final BroadcastRecord br = mPendingBroadcast;
if (br != null && br.curApp.pid == app.pid) {
+ if (br.curApp != app) {
+ Slog.e(TAG, "App mismatch when sending pending broadcast to "
+ + app.processName + ", intended target is " + br.curApp.processName);
+ return false;
+ }
try {
mPendingBroadcast = null;
processCurBroadcastLocked(br, app);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 64dea57..7587847 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -746,9 +746,8 @@
BluetoothProfile.A2DP);
}
- mHdmiManager =
- (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE);
- if (mHdmiManager != null) {
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
+ mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
synchronized (mHdmiManager) {
mHdmiTvClient = mHdmiManager.getTvClient();
if (mHdmiTvClient != null) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 61af8ed..d6cc9fc 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -102,9 +102,6 @@
// Trigger proximity if distance is less than 5 cm.
private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
- // Brightness animation ramp rate in brightness units per second.
- private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
-
private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -243,8 +240,9 @@
private boolean mAppliedDimming;
private boolean mAppliedLowPower;
- // Brightness ramp rate fast.
+ // Brightness animation ramp rates in brightness units per second
private final int mBrightnessRampRateFast;
+ private final int mBrightnessRampRateSlow;
// The controller for the automatic brightness level.
private AutomaticBrightnessController mAutomaticBrightnessController;
@@ -307,6 +305,8 @@
mBrightnessRampRateFast = resources.getInteger(
com.android.internal.R.integer.config_brightness_ramp_rate_fast);
+ mBrightnessRampRateSlow = resources.getInteger(
+ com.android.internal.R.integer.config_brightness_ramp_rate_slow);
int lightSensorRate = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
@@ -703,7 +703,7 @@
if (!mPendingScreenOff) {
if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
animateScreenBrightness(brightness,
- slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
+ slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
} else {
animateScreenBrightness(brightness, 0);
}
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index d9af7cb..07fa2ce 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -20,6 +20,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.content.BroadcastReceiver;
@@ -361,13 +362,12 @@
if (setActivated) {
mController.setActivated(activated);
}
- updateNextAlarm();
+ updateNextAlarm(mIsActivated, now);
}
- private void updateNextAlarm() {
- if (mIsActivated != null) {
- final Calendar now = Calendar.getInstance();
- final Calendar next = mIsActivated ? mEndTime.getDateTimeAfter(now)
+ private void updateNextAlarm(@Nullable Boolean activated, @NonNull Calendar now) {
+ if (activated != null) {
+ final Calendar next = activated ? mEndTime.getDateTimeAfter(now)
: mStartTime.getDateTimeAfter(now);
mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null);
}
@@ -396,10 +396,11 @@
@Override
public void onActivated(boolean activated) {
+ final Calendar now = Calendar.getInstance();
if (mIsActivated != null) {
- mLastActivatedTime = Calendar.getInstance();
+ mLastActivatedTime = now;
}
- updateNextAlarm();
+ updateNextAlarm(activated, now);
}
@Override
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d8e5f63..9ca609f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -133,7 +133,6 @@
import android.os.HandlerThread;
import android.os.IDeviceIdleController;
import android.os.INetworkManagementService;
-import android.os.IPowerManager;
import android.os.Message;
import android.os.MessageQueue.IdleHandler;
import android.os.PowerManager;
@@ -287,7 +286,6 @@
private static final int MSG_LIMIT_REACHED = 5;
private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
- private static final int MSG_SCREEN_ON_CHANGED = 8;
private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
@@ -295,7 +293,6 @@
private final Context mContext;
private final IActivityManager mActivityManager;
- private final IPowerManager mPowerManager;
private final INetworkStatsService mNetworkStats;
private final INetworkManagementService mNetworkManager;
private UsageStatsManagerInternal mUsageStats;
@@ -313,7 +310,6 @@
@GuardedBy("allLocks") volatile boolean mSystemReady;
- @GuardedBy("mUidRulesFirstLock") volatile boolean mScreenOn;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
@GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
@GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode;
@@ -419,9 +415,8 @@
// TODO: migrate notifications to SystemUI
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
- IPowerManager powerManager, INetworkStatsService networkStats,
- INetworkManagementService networkManagement) {
- this(context, activityManager, powerManager, networkStats, networkManagement,
+ INetworkStatsService networkStats, INetworkManagementService networkManagement) {
+ this(context, activityManager, networkStats, networkManagement,
NtpTrustedTime.getInstance(context), getSystemDir(), false);
}
@@ -430,12 +425,10 @@
}
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
- IPowerManager powerManager, INetworkStatsService networkStats,
- INetworkManagementService networkManagement, TrustedTime time, File systemDir,
- boolean suppressDefaultPolicy) {
+ INetworkStatsService networkStats, INetworkManagementService networkManagement,
+ TrustedTime time, File systemDir, boolean suppressDefaultPolicy) {
mContext = checkNotNull(context, "missing context");
mActivityManager = checkNotNull(activityManager, "missing activityManager");
- mPowerManager = checkNotNull(powerManager, "missing powerManager");
mNetworkStats = checkNotNull(networkStats, "missing networkStats");
mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
@@ -619,8 +612,6 @@
}
}
- updateScreenOn();
-
try {
mActivityManager.registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE);
@@ -629,14 +620,6 @@
// ignored; both services live in system_server
}
- // TODO: traverse existing processes to know foreground state, or have
- // activitymanager dispatch current state when new observer attached.
-
- final IntentFilter screenFilter = new IntentFilter();
- screenFilter.addAction(Intent.ACTION_SCREEN_ON);
- screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
- mContext.registerReceiver(mScreenReceiver, screenFilter);
-
// listen for changes to power save whitelist
final IntentFilter whitelistFilter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
@@ -735,15 +718,6 @@
}
};
- final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // screen-related broadcasts are protected by system, no need
- // for permissions check.
- mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
- }
- };
-
final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -1076,6 +1050,8 @@
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
+ builder.setDefaults(Notification.DEFAULT_ALL);
+ builder.setPriority(Notification.PRIORITY_HIGH);
final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
builder.setDeleteIntent(PendingIntent.getBroadcast(
@@ -2524,7 +2500,7 @@
private boolean isUidStateForegroundUL(int state) {
// only really in foreground when screen is also on
- return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
+ return state <= ActivityManager.PROCESS_STATE_TOP;
}
/**
@@ -2595,31 +2571,6 @@
}
}
- private void updateScreenOn() {
- synchronized (mUidRulesFirstLock) {
- try {
- mScreenOn = mPowerManager.isInteractive();
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
- updateRulesForScreenUL();
- }
- }
-
- /**
- * Update rules that might be changed by {@link #mScreenOn} value.
- */
- private void updateRulesForScreenUL() {
- // only update rules for anyone with foreground activities
- final int size = mUidState.size();
- for (int i = 0; i < size; i++) {
- if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
- final int uid = mUidState.keyAt(i);
- updateRestrictionRulesForUidUL(uid);
- }
- }
- }
-
static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
@@ -3001,12 +2952,8 @@
mUidRules.put(uid, newUidRules);
}
- boolean changed = false;
-
// Second step: apply bw changes based on change of state.
if (newRule != oldRule) {
- changed = true;
-
if ((newRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
// Temporarily whitelist foreground app, removing from blacklist if necessary
// (since bw_penalty_box prevails over bw_happy_box).
@@ -3086,7 +3033,6 @@
final boolean isIdle = isUidIdle(uid);
final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
- final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
@@ -3109,7 +3055,7 @@
final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
if (LOGV) {
- Log.v(TAG, "updateRulesForNonMeteredNetworksUL(" + uid + ")"
+ Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
+ ", isIdle: " + isIdle
+ ", mRestrictPower: " + mRestrictPower
+ ", mDeviceIdleMode: " + mDeviceIdleMode
@@ -3351,10 +3297,6 @@
}
return true;
}
- case MSG_SCREEN_ON_CHANGED: {
- updateScreenOn();
- return true;
- }
case MSG_UPDATE_INTERFACE_QUOTA: {
removeInterfaceQuota((String) msg.obj);
// int params need to be stitched back into a long
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4994d6b..ab83c11 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -364,6 +364,7 @@
private static final boolean DEBUG_TRIAGED_MISSING = false;
private static final boolean DEBUG_APP_DATA = false;
+ /** REMOVE. According to Svet, this was only used to reset permissions during development. */
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
private static final boolean DISABLE_EPHEMERAL_APPS = !Build.IS_DEBUGGABLE;
@@ -801,10 +802,9 @@
PackageParser.ActivityIntentInfo filter = filters.get(m);
domainsSet.addAll(filter.getHostsList());
}
- ArrayList<String> domainsList = new ArrayList<>(domainsSet);
synchronized (mPackages) {
if (mSettings.createIntentFilterVerificationIfNeededLPw(
- packageName, domainsList) != null) {
+ packageName, domainsSet) != null) {
scheduleWriteSettingsLocked();
}
}
@@ -2873,7 +2873,6 @@
SystemConfig systemConfig = SystemConfig.getInstance();
ArraySet<String> packages = systemConfig.getLinkedApps();
- ArraySet<String> domains = new ArraySet<String>();
for (String packageName : packages) {
PackageParser.Package pkg = mPackages.get(packageName);
@@ -2883,16 +2882,19 @@
continue;
}
- domains.clear();
+ ArraySet<String> domains = null;
for (PackageParser.Activity a : pkg.activities) {
for (ActivityIntentInfo filter : a.intents) {
if (hasValidDomains(filter)) {
+ if (domains == null) {
+ domains = new ArraySet<String>();
+ }
domains.addAll(filter.getHostsList());
}
}
}
- if (domains.size() > 0) {
+ if (domains != null && domains.size() > 0) {
if (DEBUG_DOMAIN_VERIFICATION) {
Slog.v(TAG, " + " + packageName);
}
@@ -2900,8 +2902,7 @@
// state w.r.t. the formal app-linkage "no verification attempted" state;
// and then 'always' in the per-user state actually used for intent resolution.
final IntentFilterVerificationInfo ivi;
- ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName,
- new ArrayList<String>(domains));
+ ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName, domains);
ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
mSettings.updateIntentFilterVerificationStatusLPw(packageName,
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, userId);
@@ -8164,12 +8165,12 @@
// Just create the setting, don't add it yet. For already existing packages
// the PkgSetting exists already and doesn't have to be created.
- pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
- destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
+ pkgSetting = mSettings.getPackageWithBenefitsLPw(pkg, origPackage, realName, suid,
+ destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
pkg.applicationInfo.primaryCpuAbi,
pkg.applicationInfo.secondaryCpuAbi,
pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
- user, false);
+ user);
if (pkgSetting == null) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Creating application package " + pkg.packageName + " failed");
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index e3866df..a4604a6 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -30,15 +30,23 @@
int appId;
PackageParser.Package pkg;
SharedUserSetting sharedUser;
+ /**
+ * Temporary holding space for the shared user ID. While parsing package settings, the
+ * shared users tag may be after the packages. In this case, we must delay linking the
+ * shared user setting with the package setting. The shared user ID lets us link the
+ * two objects.
+ */
+ private int sharedUserId;
PackageSetting(String name, String realName, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString,
int pVersionCode, int pkgFlags, int privateFlags, String parentPackageName,
- List<String> childPackageNames) {
+ List<String> childPackageNames, int sharedUserId) {
super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames);
+ this.sharedUserId = sharedUserId;
}
/**
@@ -47,10 +55,14 @@
*/
PackageSetting(PackageSetting orig) {
super(orig);
+ doCopy(orig);
+ }
- appId = orig.appId;
- pkg = orig.pkg;
- sharedUser = orig.sharedUser;
+ public int getSharedUserId() {
+ if (sharedUser != null) {
+ return sharedUser.userId;
+ }
+ return sharedUserId;
}
@Override
@@ -60,6 +72,18 @@
+ " " + name + "/" + appId + "}";
}
+ public void copyFrom(PackageSetting orig) {
+ super.copyFrom(orig);
+ doCopy(orig);
+ }
+
+ private void doCopy(PackageSetting orig) {
+ appId = orig.appId;
+ pkg = orig.pkg;
+ sharedUser = orig.sharedUser;
+ sharedUserId = orig.sharedUserId;
+ }
+
public PermissionsState getPermissionsState() {
return (sharedUser != null)
? sharedUser.getPermissionsState()
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 14ca72c..c08bc57 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -147,51 +147,12 @@
secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode);
}
- /**
- * New instance of PackageSetting with one-level-deep cloning.
- */
- @SuppressWarnings("unchecked")
+ /** New instance of PackageSetting with one-level-deep cloning. */
PackageSettingBase(PackageSettingBase base) {
super(base);
-
name = base.name;
realName = base.realName;
- codePath = base.codePath;
- codePathString = base.codePathString;
- resourcePath = base.resourcePath;
- resourcePathString = base.resourcePathString;
- legacyNativeLibraryPathString = base.legacyNativeLibraryPathString;
- primaryCpuAbiString = base.primaryCpuAbiString;
- secondaryCpuAbiString = base.secondaryCpuAbiString;
- cpuAbiOverrideString = base.cpuAbiOverrideString;
- timeStamp = base.timeStamp;
- firstInstallTime = base.firstInstallTime;
- lastUpdateTime = base.lastUpdateTime;
- versionCode = base.versionCode;
-
- uidError = base.uidError;
-
- signatures = new PackageSignatures(base.signatures);
-
- installPermissionsFixed = base.installPermissionsFixed;
- userState.clear();
- for (int i=0; i<base.userState.size(); i++) {
- userState.put(base.userState.keyAt(i),
- new PackageUserState(base.userState.valueAt(i)));
- }
- installStatus = base.installStatus;
-
- origPackage = base.origPackage;
-
- installerPackageName = base.installerPackageName;
- isOrphaned = base.isOrphaned;
- volumeUuid = base.volumeUuid;
-
- keySetData = new PackageKeySetData(base.keySetData);
-
- parentPackageName = base.parentPackageName;
- childPackageNames = (base.childPackageNames != null)
- ? new ArrayList<>(base.childPackageNames) : null;
+ doCopy(base);
}
void init(File codePath, File resourcePath, String legacyNativeLibraryPathString,
@@ -237,27 +198,47 @@
}
/**
- * Make a shallow copy of this package settings.
+ * Makes a shallow copy of the given package settings.
+ *
+ * NOTE: For some fields [such as keySetData, signatures, userState, verificationInfo, etc...],
+ * the original object is copied and a new one is not created.
*/
- public void copyFrom(PackageSettingBase base) {
- mPermissionsState.copyFrom(base.mPermissionsState);
- primaryCpuAbiString = base.primaryCpuAbiString;
- secondaryCpuAbiString = base.secondaryCpuAbiString;
- cpuAbiOverrideString = base.cpuAbiOverrideString;
- timeStamp = base.timeStamp;
- firstInstallTime = base.firstInstallTime;
- lastUpdateTime = base.lastUpdateTime;
- signatures = base.signatures;
- installPermissionsFixed = base.installPermissionsFixed;
+ public void copyFrom(PackageSettingBase orig) {
+ super.copyFrom(orig);
+ doCopy(orig);
+ }
+
+ private void doCopy(PackageSettingBase orig) {
+ childPackageNames = (orig.childPackageNames != null)
+ ? new ArrayList<>(orig.childPackageNames) : null;
+ codePath = orig.codePath;
+ codePathString = orig.codePathString;
+ cpuAbiOverrideString = orig.cpuAbiOverrideString;
+ firstInstallTime = orig.firstInstallTime;
+ installPermissionsFixed = orig.installPermissionsFixed;
+ installStatus = orig.installStatus;
+ installerPackageName = orig.installerPackageName;
+ isOrphaned = orig.isOrphaned;
+ keySetData = orig.keySetData;
+ lastUpdateTime = orig.lastUpdateTime;
+ legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
+ // Intentionally skip oldCodePaths; it's not relevant for copies
+ origPackage = orig.origPackage;
+ parentPackageName = orig.parentPackageName;
+ primaryCpuAbiString = orig.primaryCpuAbiString;
+ resourcePath = orig.resourcePath;
+ resourcePathString = orig.resourcePathString;
+ secondaryCpuAbiString = orig.secondaryCpuAbiString;
+ signatures = orig.signatures;
+ timeStamp = orig.timeStamp;
+ uidError = orig.uidError;
userState.clear();
- for (int i=0; i<base.userState.size(); i++) {
- userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
+ for (int i=0; i<orig.userState.size(); i++) {
+ userState.put(orig.userState.keyAt(i), orig.userState.valueAt(i));
}
- installStatus = base.installStatus;
- keySetData = base.keySetData;
- verificationInfo = base.verificationInfo;
- installerPackageName = base.installerPackageName;
- volumeUuid = base.volumeUuid;
+ verificationInfo = orig.verificationInfo;
+ versionCode = orig.versionCode;
+ volumeUuid = orig.volumeUuid;
}
private PackageUserState modifyUserState(int userId) {
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
deleted file mode 100644
index da73085..0000000
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm;
-
-import java.io.File;
-import java.util.List;
-
-final class PendingPackage extends PackageSettingBase {
- final int sharedId;
-
- PendingPackage(String name, String realName, File codePath, File resourcePath,
- String legacyNativeLibraryPathString, String primaryCpuAbiString,
- String secondaryCpuAbiString, String cpuAbiOverrideString, int sharedId,
- int pVersionCode, int pkgFlags, int pkgPrivateFlags, String parentPackageName,
- List<String> childPackageNames) {
- super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
- primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
- pVersionCode, pkgFlags, pkgPrivateFlags, parentPackageName, childPackageNames);
- this.sharedId = sharedId;
- }
-}
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index a6350fe..8970556 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -19,6 +19,7 @@
import android.content.pm.PackageParser;
import android.content.pm.Signature;
import android.os.Environment;
+import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -64,6 +65,8 @@
// to synchronize access during policy load and access attempts.
private static List<Policy> sPolicies = new ArrayList<>();
+ private static final String PROP_FORCE_RESTORECON = "sys.force_restorecon";
+
/** Path to version on rootfs */
private static final File VERSION_FILE = new File("/selinux_version");
@@ -322,6 +325,11 @@
* @return Returns true if the restorecon should occur or false otherwise.
*/
public static boolean isRestoreconNeeded(File file) {
+ // To investigate boot timing, allow a property to always force restorecon
+ if (SystemProperties.getBoolean(PROP_FORCE_RESTORECON, false)) {
+ return true;
+ }
+
try {
final byte[] buf = new byte[20];
final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SEAPP_HASH, buf);
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 2921032..71e8d51 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -30,10 +30,19 @@
mPermissionsState = new PermissionsState();
}
- SettingBase(SettingBase base) {
- pkgFlags = base.pkgFlags;
- pkgPrivateFlags = base.pkgPrivateFlags;
- mPermissionsState = new PermissionsState(base.mPermissionsState);
+ SettingBase(SettingBase orig) {
+ mPermissionsState = new PermissionsState();
+ doCopy(orig);
+ }
+
+ public void copyFrom(SettingBase orig) {
+ doCopy(orig);
+ }
+
+ private void doCopy(SettingBase orig) {
+ pkgFlags = orig.pkgFlags;
+ pkgPrivateFlags = orig.pkgPrivateFlags;
+ mPermissionsState.copyFrom(orig.mPermissionsState);
}
public PermissionsState getPermissionsState() {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 31a1c36..52313b1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -166,6 +166,7 @@
private static final boolean DEBUG_STOPPED = false;
private static final boolean DEBUG_MU = false;
private static final boolean DEBUG_KERNEL = false;
+ private static final boolean DEBUG_PARSER = false;
private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
@@ -393,7 +394,7 @@
* TODO: make this just a local variable that is passed in during package
* scanning to make it less confusing.
*/
- private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
+ private final ArrayList<PackageSetting> mPendingPackages = new ArrayList<>();
private final File mSystemDir;
@@ -427,18 +428,22 @@
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
- PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
+ PackageSetting getPackageLPw(String pkgName) {
+ return peekPackageLPr(pkgName);
+ }
+
+ PackageSetting getPackageWithBenefitsLPw(PackageParser.Package pkg, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
- int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add)
+ int pkgFlags, int pkgPrivateFlags, UserHandle user)
throws PackageManagerException {
final String name = pkg.packageName;
final String parentPackageName = (pkg.parentPackage != null)
? pkg.parentPackage.packageName : null;
- PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
- resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
- pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /*allowInstall*/,
- parentPackageName, pkg.getChildPackageNames());
+ PackageSetting p = getPackageWithBenefitsLPw(name, origPackage, realName, sharedUser,
+ codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbi,
+ secondaryCpuAbi, pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user,
+ true /*allowInstall*/, parentPackageName, pkg.getChildPackageNames());
return p;
}
@@ -602,7 +607,7 @@
p = new PackageSetting(name, realName, codePath, resourcePath,
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, parentPackageName,
- childPackageNames);
+ childPackageNames, 0 /*userId*/);
p.appId = uid;
if (addUserIdLPw(uid, p, name)) {
mPackages.put(name, p);
@@ -679,11 +684,11 @@
}
}
- private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
+ private PackageSetting getPackageWithBenefitsLPw(String name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,
- UserHandle installUser, boolean add, boolean allowInstall, String parentPackage,
+ UserHandle installUser, boolean allowInstall, String parentPackage,
List<String> childPackageNames) throws PackageManagerException {
final UserManagerService userManager = UserManagerService.getInstance();
final PackageSetting disabledPackage = getDisabledSystemPkgLPr(name);
@@ -714,11 +719,6 @@
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Creating application package " + name + " failed");
}
- if (add) {
- // Finish adding new package by adding it and updating shared
- // user preferences
- addPackageSettingLPw(p, name, sharedUser);
- }
}
if (peekPackageLPr(name) != null) {
final List<UserInfo> allUsers = getAllUsers(UserManagerService.getInstance());
@@ -857,7 +857,7 @@
pkgSetting = new PackageSetting(originalPkg.name, pkgName, codePath, resourcePath,
legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
- parentPkgName, childPkgNames);
+ parentPkgName, childPkgNames, 0 /*sharedUserId*/);
if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+ pkgName + " is adopting original package " + originalPkg.name);
// Note that we will retain the new package's signature so
@@ -876,7 +876,7 @@
pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath,
legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
- parentPkgName, childPkgNames);
+ parentPkgName, childPkgNames, 0 /*sharedUserId*/);
pkgSetting.setTimeStamp(codePath.lastModified());
pkgSetting.sharedUser = sharedUser;
// If this is not a system app, it starts out stopped.
@@ -1025,15 +1025,14 @@
if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
}
- addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
+ addPackageSettingLPw(p, p.sharedUser);
}
// Utility method that adds a PackageSetting to mPackages and
// completes updating the shared user attributes and any restored
// app link verification state
- private void addPackageSettingLPw(PackageSetting p, String name,
- SharedUserSetting sharedUser) {
- mPackages.put(name, p);
+ private void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
+ mPackages.put(p.name, p);
if (sharedUser != null) {
if (p.sharedUser != null && p.sharedUser != sharedUser) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
@@ -1067,12 +1066,12 @@
}
}
- IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(name);
+ IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(p.name);
if (ivi != null) {
if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.i(TAG, "Applying restored IVI for " + name + " : " + ivi.getStatusString());
+ Slog.i(TAG, "Applying restored IVI for " + p.name + " : " + ivi.getStatusString());
}
- mRestoredIntentFilterVerifications.remove(name);
+ mRestoredIntentFilterVerifications.remove(p.name);
p.setIntentFilterVerificationInfo(ivi);
}
}
@@ -1320,7 +1319,7 @@
/* package protected */
IntentFilterVerificationInfo createIntentFilterVerificationIfNeededLPw(String packageName,
- ArrayList<String> domains) {
+ ArraySet<String> domains) {
PackageSetting ps = mPackages.get(packageName);
if (ps == null) {
if (DEBUG_DOMAIN_VERIFICATION) {
@@ -1595,7 +1594,9 @@
throws XmlPullParserException, IOException {
IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser);
packageSetting.setIntentFilterVerificationInfo(ivi);
- Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName());
+ if (DEBUG_PARSER) {
+ Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName());
+ }
}
private void readRestoredIntentFilterVerifications(XmlPullParser parser)
@@ -3039,30 +3040,22 @@
final int N = mPendingPackages.size();
for (int i = 0; i < N; i++) {
- final PendingPackage pp = mPendingPackages.get(i);
- Object idObj = getUserIdLPr(pp.sharedId);
- if (idObj != null && idObj instanceof SharedUserSetting) {
- try {
- PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
- (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
- pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
- pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags,
- pp.pkgPrivateFlags, null /*installUser*/, true /*add*/,
- false /*allowInstall*/, pp.parentPackageName, pp.childPackageNames);
- p.copyFrom(pp);
- } catch (PackageManagerException e) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Unable to create application package for " + pp.name);
- continue;
- }
+ final PackageSetting p = mPendingPackages.get(i);
+ final int sharedUserId = p.getSharedUserId();
+ final Object idObj = getUserIdLPr(sharedUserId);
+ if (idObj instanceof SharedUserSetting) {
+ final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
+ p.sharedUser = sharedUser;
+ p.appId = sharedUser.userId;
+ addPackageSettingLPw(p, sharedUser);
} else if (idObj != null) {
- String msg = "Bad package setting: package " + pp.name + " has shared uid "
- + pp.sharedId + " that is not a shared uid\n";
+ String msg = "Bad package setting: package " + p.name + " has shared uid "
+ + sharedUserId + " that is not a shared uid\n";
mReadMessages.append(msg);
PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
} else {
- String msg = "Bad package setting: package " + pp.name + " has shared uid "
- + pp.sharedId + " that is not defined\n";
+ String msg = "Bad package setting: package " + p.name + " has shared uid "
+ + sharedUserId + " that is not defined\n";
mReadMessages.append(msg);
PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
}
@@ -3535,7 +3528,7 @@
PackageSetting ps = new PackageSetting(name, realName, codePathFile,
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags,
- parentPackageName, null);
+ parentPackageName, null /*childPackageNames*/, 0 /*sharedUserId*/);
String timeStampStr = parser.getAttributeValue(null, "ft");
if (timeStampStr != null) {
try {
@@ -3627,7 +3620,7 @@
long timeStamp = 0;
long firstInstallTime = 0;
long lastUpdateTime = 0;
- PackageSettingBase packageSetting = null;
+ PackageSetting packageSetting = null;
String version = null;
int versionCode = 0;
String parentPackageName;
@@ -3746,7 +3739,8 @@
if (PackageManagerService.DEBUG_SETTINGS)
Log.v(PackageManagerService.TAG, "Reading package: " + name + " userId=" + idStr
+ " sharedUserId=" + sharedIdStr);
- int userId = idStr != null ? Integer.parseInt(idStr) : 0;
+ final int userId = idStr != null ? Integer.parseInt(idStr) : 0;
+ final int sharedUserId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
if (resourcePathStr == null) {
resourcePathStr = codePathStr;
}
@@ -3765,7 +3759,7 @@
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
- pkgPrivateFlags, parentPackageName, null);
+ pkgPrivateFlags, parentPackageName, null /*childPackageNames*/);
if (PackageManagerService.DEBUG_SETTINGS)
Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
+ userId + " pkg=" + packageSetting);
@@ -3779,20 +3773,19 @@
packageSetting.lastUpdateTime = lastUpdateTime;
}
} else if (sharedIdStr != null) {
- userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
- if (userId > 0) {
- packageSetting = new PendingPackage(name.intern(), realName, new File(
+ if (sharedUserId > 0) {
+ packageSetting = new PackageSetting(name.intern(), realName, new File(
codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
- userId, versionCode, pkgFlags, pkgPrivateFlags, parentPackageName,
- null);
+ versionCode, pkgFlags, pkgPrivateFlags, parentPackageName,
+ null /*childPackageNames*/, sharedUserId);
packageSetting.setTimeStamp(timeStamp);
packageSetting.firstInstallTime = firstInstallTime;
packageSetting.lastUpdateTime = lastUpdateTime;
- mPendingPackages.add((PendingPackage) packageSetting);
+ mPendingPackages.add(packageSetting);
if (PackageManagerService.DEBUG_SETTINGS)
Log.i(PackageManagerService.TAG, "Reading package " + name
- + ": sharedUserId=" + userId + " pkg=" + packageSetting);
+ + ": sharedUserId=" + sharedUserId + " pkg=" + packageSetting);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index d5767b4..c1fc7f1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -878,6 +878,9 @@
saveUserInternalLocked(userId, os, /* forBackup= */ false);
file.finishWrite(os);
+
+ // Remove all dangling bitmap files.
+ cleanupDanglingBitmapDirectoriesLocked(userId);
} catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(os);
@@ -929,7 +932,6 @@
}
try {
final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
- cleanupDanglingBitmapDirectoriesLocked(userId, ret);
return ret;
} catch (IOException | XmlPullParserException e) {
Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
@@ -1062,9 +1064,22 @@
}
}
- // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
+ // Requires mLock held, but "Locked" prefix would look weired so we just say "L".
protected boolean isUserUnlockedL(@UserIdInt int userId) {
- return mUnlockedUsers.get(userId);
+ // First, check the local copy.
+ if (mUnlockedUsers.get(userId)) {
+ return true;
+ }
+ // If the local copy says the user is locked, check with AM for the actual state, since
+ // the user might just have been unlocked.
+ // Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false
+ // when the user is STOPPING, which we still want to consider as "unlocked".
+ final long token = injectClearCallingIdentity();
+ try {
+ return mUserManager.isUserUnlockingOrUnlocked(userId);
+ } finally {
+ injectRestoreCallingIdentity(token);
+ }
}
// Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
@@ -1125,14 +1140,8 @@
// === Caller validation ===
void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) {
- if (shortcut.getBitmapPath() != null) {
- if (DEBUG) {
- Slog.d(TAG, "Removing " + shortcut.getBitmapPath());
- }
- new File(shortcut.getBitmapPath()).delete();
-
- shortcut.setBitmapPath(null);
- }
+ // Do not remove the actual bitmap file yet, because if the device crashes before saving
+ // he XML we'd lose the icon. We just remove all dangling files after saving the XML.
shortcut.setIconResourceId(0);
shortcut.setIconResName(null);
shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES);
@@ -1148,13 +1157,14 @@
}
}
- private void cleanupDanglingBitmapDirectoriesLocked(
- @UserIdInt int userId, @NonNull ShortcutUser user) {
+ private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) {
if (DEBUG) {
Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId);
}
final long start = injectElapsedRealtime();
+ final ShortcutUser user = getUserShortcutsLocked(userId);
+
final File bitmapDir = getUserBitmapFilePath(userId);
final File[] children = bitmapDir.listFiles();
if (children == null) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 772c64e..3df13a9 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -26,11 +26,9 @@
import android.app.ActivityManagerNative;
import android.content.ContentResolver;
import android.content.Context;
-import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.persistentdata.PersistentDataBlockManager;
@@ -188,8 +186,7 @@
serializer.endTag(null, tag);
}
- public static void readRestrictions(XmlPullParser parser, Bundle restrictions)
- throws IOException {
+ public static void readRestrictions(XmlPullParser parser, Bundle restrictions) {
for (String key : USER_RESTRICTIONS) {
final String value = parser.getAttributeValue(null, key);
if (value != null) {
@@ -437,7 +434,13 @@
if (newValue) {
PersistentDataBlockManager manager = (PersistentDataBlockManager) context
.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
- if (manager != null && manager.getOemUnlockEnabled()) {
+ if (manager != null
+ && manager.getOemUnlockEnabled()
+ && manager.getFlashLockState()
+ != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) {
+ // Only disable OEM unlock if the bootloader is locked. If it's already
+ // unlocked, setting the OEM unlock enabled flag to false has no effect
+ // (the bootloader would remain unlocked).
manager.setOemUnlockEnabled(false);
}
}
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 6fc15f0..bb91f76 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -103,6 +103,7 @@
private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
+ private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
private final Context mContext;
private final WindowManagerFuncs mWindowManagerFuncs;
@@ -298,6 +299,8 @@
mItems.add(getVoiceAssistAction());
} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
mItems.add(getAssistAction());
+ } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
+ mItems.add(new RestartAction());
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -369,6 +372,38 @@
}
}
+ private final class RestartAction extends SinglePressAction implements LongPressAction {
+ private RestartAction() {
+ super(R.drawable.ic_restart, R.string.global_action_restart);
+ }
+
+ @Override
+ public boolean onLongPress() {
+ UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+ mWindowManagerFuncs.rebootSafeMode(true);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ mWindowManagerFuncs.reboot(false /* confirm */);
+ }
+ }
+
+
private class BugReportAction extends SinglePressAction implements LongPressAction {
public BugReportAction() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 60fbabf..9ce147d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -7392,8 +7392,8 @@
}
private boolean areSystemNavigationKeysEnabled() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0) == 1;
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
}
@Override
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index fd63d48..aaac297 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -37,6 +37,7 @@
private static final int TYPE_AGENT_CONNECTED = 4;
private static final int TYPE_AGENT_STOPPED = 5;
private static final int TYPE_MANAGING_TRUST = 6;
+ private static final int TYPE_POLICY_CHANGED = 7;
private static final int HISTORY_LIMIT = 200;
@@ -99,6 +100,10 @@
addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, 0, managing));
}
+ public void logDevicePolicyChanged() {
+ addEvent(new Event(TYPE_POLICY_CHANGED, UserHandle.USER_ALL, null, null, 0, 0, false));
+ }
+
private void addEvent(Event e) {
if (mEvents.size() >= HISTORY_LIMIT) {
mEvents.removeFirst();
@@ -112,7 +117,8 @@
Iterator<Event> iter = mEvents.descendingIterator();
while (iter.hasNext() && count < limit) {
Event ev = iter.next();
- if (userId != UserHandle.USER_ALL && userId != ev.userId) {
+ if (userId != UserHandle.USER_ALL && userId != ev.userId
+ && ev.userId != UserHandle.USER_ALL) {
continue;
}
@@ -122,11 +128,13 @@
if (userId == UserHandle.USER_ALL) {
writer.print("user="); writer.print(ev.userId); writer.print(", ");
}
- writer.print("agent=");
- if (duplicateSimpleNames) {
- writer.print(ev.agent.flattenToShortString());
- } else {
- writer.print(getSimpleName(ev.agent));
+ if (ev.agent != null) {
+ writer.print("agent=");
+ if (duplicateSimpleNames) {
+ writer.print(ev.agent.flattenToShortString());
+ } else {
+ writer.print(getSimpleName(ev.agent));
+ }
}
switch (ev.type) {
case TYPE_GRANT_TRUST:
@@ -181,6 +189,8 @@
return "AgentStopped";
case TYPE_MANAGING_TRUST:
return "ManagingTrust";
+ case TYPE_POLICY_CHANGED:
+ return "DevicePolicyChanged";
default:
return "Unknown(" + type + ")";
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index e60488a..216afe6 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -434,12 +434,17 @@
}
void updateDevicePolicyFeatures() {
+ boolean changed = false;
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
if (info.agent.isConnected()) {
info.agent.updateDevicePolicyFeatures();
+ changed = true;
}
}
+ if (changed) {
+ mArchive.logDevicePolicyChanged();
+ }
}
private void removeAgentsOfPackage(String packageName) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 95fbf55..76f2f0e 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1400,9 +1400,7 @@
wallpaper.whichPending = which;
wallpaper.setComplete = completion;
wallpaper.cropHint.set(cropHint);
- if ((which & FLAG_SYSTEM) != 0) {
- wallpaper.allowBackup = allowBackup;
- }
+ wallpaper.allowBackup = allowBackup;
}
return pfd;
} finally {
@@ -1753,12 +1751,14 @@
}
@Override
- public boolean isWallpaperBackupEligible(int userId) {
+ public boolean isWallpaperBackupEligible(int which, int userId) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Only the system may call isWallpaperBackupEligible");
}
- WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
+ WallpaperData wallpaper = (which == FLAG_LOCK)
+ ? mWallpaperMap.get(userId)
+ : mLockWallpaperMap.get(userId);
return (wallpaper != null) ? wallpaper.allowBackup : false;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c78e94b..d3dab44 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -517,6 +517,11 @@
// placement for this window during this period, one or more frame will
// show up with wrong position or scale.
win.mWinAnimator.mAnimating = false;
+
+ if (win.mDestroying) {
+ win.mDestroying = false;
+ mService.mDestroySurface.remove(win);
+ }
}
}
requestUpdateWallpaperIfNeeded();
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 9d0fb61..d0167bb 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -94,10 +94,7 @@
float mOriginalX, mOriginalY;
float mCurrentX, mCurrentY;
float mThumbOffsetX, mThumbOffsetY;
- InputChannel mServerChannel, mClientChannel;
- DragInputEventReceiver mInputEventReceiver;
- InputApplicationHandle mDragApplicationHandle;
- InputWindowHandle mDragWindowHandle;
+ InputInterceptor mInputInterceptor;
WindowState mTargetWindow;
ArrayList<WindowState> mNotifiedWindows;
boolean mDragInProgress;
@@ -130,16 +127,13 @@
mNotifiedWindows = null;
}
- /**
- * @param display The Display that the window being dragged is on.
- */
- void register(Display display) {
- if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
- if (mClientChannel != null) {
- Slog.e(TAG_WM, "Duplicate register of drag input channel");
- } else {
- mDisplayContent = mService.getDisplayContentLocked(display.getDisplayId());
+ class InputInterceptor {
+ InputChannel mServerChannel, mClientChannel;
+ DragInputEventReceiver mInputEventReceiver;
+ InputApplicationHandle mDragApplicationHandle;
+ InputWindowHandle mDragWindowHandle;
+ InputInterceptor(Display display) {
InputChannel[] channels = InputChannel.openInputChannelPair("drag");
mServerChannel = channels[0];
mClientChannel = channels[1];
@@ -188,13 +182,8 @@
}
mService.pauseRotationLocked();
}
- }
- void unregister() {
- if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel");
- if (mClientChannel == null) {
- Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
- } else {
+ void tearDown() {
mService.mInputManager.unregisterInputChannel(mServerChannel);
mInputEventReceiver.dispose();
mInputEventReceiver = null;
@@ -214,6 +203,40 @@
}
}
+ InputChannel getInputChannel() {
+ return mInputInterceptor == null ? null : mInputInterceptor.mServerChannel;
+ }
+
+ InputWindowHandle getInputWindowHandle() {
+ return mInputInterceptor == null ? null : mInputInterceptor.mDragWindowHandle;
+ }
+
+ /**
+ * @param display The Display that the window being dragged is on.
+ */
+ void register(Display display) {
+ if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
+ if (mInputInterceptor != null) {
+ Slog.e(TAG_WM, "Duplicate register of drag input channel");
+ } else {
+ mInputInterceptor = new InputInterceptor(display);
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ }
+ }
+
+ void unregister() {
+ if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel");
+ if (mInputInterceptor == null) {
+ Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
+ } else {
+ // Input channel should be disposed on the thread where the input is being handled.
+ mService.mH.obtainMessage(
+ H.TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor).sendToTarget();
+ mInputInterceptor = null;
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ }
+ }
+
int getDragLayerLw() {
return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
@@ -397,8 +420,6 @@
// free our resources and drop all the object references
reset();
mService.mDragState = null;
-
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
}
void notifyMoveLw(float x, float y) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index b9c55a5..535ce9d 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -249,7 +249,7 @@
if (DEBUG_DRAG) {
Log.d(TAG_WM, "Inserting drag window");
}
- final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle;
+ final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
if (dragWindowHandle != null) {
addInputWindowHandleLw(dragWindowHandle);
} else {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 08c0a4b..cb99461 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -324,16 +324,16 @@
}
Display display = displayContent.getDisplay();
mService.mDragState.register(display);
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
- mService.mDragState.mServerChannel)) {
+ mService.mDragState.getInputChannel())) {
Slog.e(TAG_WM, "Unable to transfer touch focus");
mService.mDragState.unregister();
+ mService.mDragState.reset();
mService.mDragState = null;
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
return false;
}
+ mService.mDragState.mDisplayContent = displayContent;
mService.mDragState.mData = data;
mService.mDragState.broadcastDragStartedLw(touchX, touchY);
mService.mDragState.overridePointerIconLw(touchSource);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 6515fbd..34fa1b0 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -119,6 +119,8 @@
// check if some got replaced and can be removed.
private boolean mRemoveReplacedWindows = false;
+ private final AppTokenList mTmpExitingAppTokens = new AppTokenList();
+
private String forceHidingToString() {
switch (mForceHiding) {
case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN";
@@ -189,10 +191,19 @@
}
}
- final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
- final int exitingCount = exitingAppTokens.size();
+ mTmpExitingAppTokens.clear();
+ mTmpExitingAppTokens.addAll(stack.mExitingAppTokens);
+
+ final int exitingCount = mTmpExitingAppTokens.size();
for (int i = 0; i < exitingCount; i++) {
- final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
+ final AppWindowAnimator appAnimator = mTmpExitingAppTokens.get(i).mAppAnimator;
+ // stepAnimation can trigger finishExit->removeWindowInnerLocked
+ // ->performSurfacePlacement
+ // performSurfacePlacement will directly manipulate the mExitingAppTokens list
+ // so we need to iterate over a copy and check for modifications.
+ if (!stack.mExitingAppTokens.contains(appAnimator)) {
+ continue;
+ }
appAnimator.wasAnimating = appAnimator.animating;
if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
setAnimating(true);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8f7896e..22120d0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -771,9 +771,16 @@
public void onInputEvent(InputEvent event) {
boolean handled = false;
try {
+ if (mDragState == null) {
+ // The drag has ended but the clean-up message has not been processed by
+ // window manager. Drop events that occur after this until window manager
+ // has a chance to clean-up the input handle.
+ handled = true;
+ return;
+ }
if (event instanceof MotionEvent
&& (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
- && mDragState != null && !mMuteInput) {
+ && !mMuteInput) {
final MotionEvent motionEvent = (MotionEvent)event;
boolean endDrag = false;
final float newX = motionEvent.getRawX();
@@ -833,6 +840,8 @@
if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
// tell all the windows that the drag has ended
synchronized (mWindowMap) {
+ // endDragLw will post back to looper to dispose the receiver
+ // since we still need the receiver for the last finishInputEvent.
mDragState.endDragLw();
}
mStylusButtonDownAtStart = false;
@@ -4718,6 +4727,12 @@
// Called by window manager policy. Not exposed externally.
@Override
+ public void reboot(boolean confirm) {
+ ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+ }
+
+ // Called by window manager policy. Not exposed externally.
+ @Override
public void rebootSafeMode(boolean confirm) {
ShutdownThread.rebootSafeMode(mContext, confirm);
}
@@ -7099,6 +7114,7 @@
public static final int RESIZE_STACK = 42;
public static final int RESIZE_TASK = 43;
+ public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
@@ -7511,7 +7527,6 @@
// !!! TODO: ANR the app that has failed to start the drag in time
if (mDragState != null) {
mDragState.unregister();
- mInputMonitor.updateInputWindowsLw(true /*force*/);
mDragState.reset();
mDragState = null;
}
@@ -7534,6 +7549,17 @@
break;
}
+ case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
+ if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
+ DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
+ if (interceptor != null) {
+ synchronized (mWindowMap) {
+ interceptor.tearDown();
+ }
+ }
+ }
+ break;
+
case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
notifyHardKeyboardStatusChange();
break;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0fcf0c7..dfee8de 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -845,6 +845,22 @@
mPendingDestroySurface = null;
}
+ void applyMagnificationSpec(MagnificationSpec spec, Matrix transform) {
+ final int surfaceInsetLeft = mWin.mAttrs.surfaceInsets.left;
+ final int surfaceInsetTop = mWin.mAttrs.surfaceInsets.top;
+
+ if (spec != null && !spec.isNop()) {
+ float scale = spec.scale;
+ transform.postScale(scale, scale);
+ transform.postTranslate(spec.offsetX, spec.offsetY);
+
+ // As we are scaling the whole surface, to keep the content
+ // in the same position we will also have to scale the surfaceInsets.
+ transform.postTranslate(-(surfaceInsetLeft*scale - surfaceInsetLeft),
+ -(surfaceInsetTop*scale - surfaceInsetTop));
+ }
+ }
+
void computeShownFrameLocked() {
final boolean selfTransformation = mHasLocalTransformation;
Transformation attachedTransformation =
@@ -935,10 +951,7 @@
if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
MagnificationSpec spec = mService.mAccessibilityController
.getMagnificationSpecForWindowLocked(mWin);
- if (spec != null && !spec.isNop()) {
- tmpMatrix.postScale(spec.scale, spec.scale);
- tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
- }
+ applyMagnificationSpec(spec, tmpMatrix);
}
// "convert" it into SurfaceFlinger's format
@@ -1037,10 +1050,7 @@
tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
- if (spec != null && !spec.isNop()) {
- tmpMatrix.postScale(spec.scale, spec.scale);
- tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
- }
+ applyMagnificationSpec(spec, tmpMatrix);
tmpMatrix.getValues(tmpFloats);
@@ -1896,11 +1906,13 @@
if (mDeferTransactionUntilFrame < 0) {
return;
}
+ final WindowState parentWindow = mWin.getParentWindow();
long time = System.currentTimeMillis();
if (time > mDeferTransactionTime + PENDING_TRANSACTION_FINISH_WAIT_TIME) {
mDeferTransactionTime = -1;
mDeferTransactionUntilFrame = -1;
- } else {
+ } else if (parentWindow != null &&
+ parentWindow.mWinAnimator.hasSurface()) {
mSurfaceController.deferTransactionUntil(
mWin.getParentWindow().mWinAnimator.mSurfaceController.getHandle(),
mDeferTransactionUntilFrame);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index c26c078..4c9211a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1462,7 +1462,7 @@
mObscured = true;
}
- if (w.mHasSurface) {
+ if (w.mHasSurface && canBeSeen) {
if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
mHoldScreen = w.mSession;
mHoldScreenWindow = w;
@@ -1485,43 +1485,39 @@
}
final int type = attrs.type;
- if (canBeSeen
- && (type == TYPE_SYSTEM_DIALOG
- || type == TYPE_SYSTEM_ERROR
- || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
+ if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+ || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mSyswin = true;
}
- if (canBeSeen) {
- // This function assumes that the contents of the default display are
- // processed first before secondary displays.
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && displayContent.isDefaultDisplay) {
- // While a dream or keyguard is showing, obscure ordinary application
- // content on secondary displays (by forcibly enabling mirroring unless
- // there is other content we want to show) but still allow opaque
- // keyguard dialogs to be shown.
- if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mObscureApplicationContentOnSecondaryDisplays = true;
- }
- mDisplayHasContent = true;
- } else if (displayContent != null &&
- (!mObscureApplicationContentOnSecondaryDisplays
- || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
- // Allow full screen keyguard presentation dialogs to be seen.
- mDisplayHasContent = true;
+ // This function assumes that the contents of the default display are
+ // processed first before secondary displays.
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (displayContent != null && displayContent.isDefaultDisplay) {
+ // While a dream or keyguard is showing, obscure ordinary application
+ // content on secondary displays (by forcibly enabling mirroring unless
+ // there is other content we want to show) but still allow opaque
+ // keyguard dialogs to be shown.
+ if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mObscureApplicationContentOnSecondaryDisplays = true;
}
- if (mPreferredRefreshRate == 0
- && w.mAttrs.preferredRefreshRate != 0) {
- mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
- }
- if (mPreferredModeId == 0
- && w.mAttrs.preferredDisplayModeId != 0) {
- mPreferredModeId = w.mAttrs.preferredDisplayModeId;
- }
- if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
- mSustainedPerformanceModeCurrent = true;
- }
+ mDisplayHasContent = true;
+ } else if (displayContent != null &&
+ (!mObscureApplicationContentOnSecondaryDisplays
+ || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
+ // Allow full screen keyguard presentation dialogs to be seen.
+ mDisplayHasContent = true;
+ }
+ if (mPreferredRefreshRate == 0
+ && w.mAttrs.preferredRefreshRate != 0) {
+ mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
+ }
+ if (mPreferredModeId == 0
+ && w.mAttrs.preferredDisplayModeId != 0) {
+ mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+ }
+ if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
+ mSustainedPerformanceModeCurrent = true;
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f0cf320..548f831 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -810,10 +810,8 @@
traceBeginAndSlog("StartNetworkPolicyManagerService");
try {
- networkPolicy = new NetworkPolicyManagerService(
- context, mActivityManagerService,
- (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE),
- networkStats, networkManagement);
+ networkPolicy = new NetworkPolicyManagerService(context,
+ mActivityManagerService, networkStats, networkManagement);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
} catch (Throwable e) {
reportWtf("starting NetworkPolicy Service", e);
@@ -1013,6 +1011,10 @@
mSystemServiceManager.startService(SoundTriggerService.class);
if (!disableNonCoreServices) {
+ if (!disableTrustManager) {
+ mSystemServiceManager.startService(TrustManagerService.class);
+ }
+
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP)) {
mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
}
@@ -1142,10 +1144,6 @@
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- if (!disableTrustManager) {
- mSystemServiceManager.startService(TrustManagerService.class);
- }
-
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
mSystemServiceManager.startService(FingerprintService.class);
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 979f160..6247089 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,17 +16,12 @@
package com.android.server;
-import static android.content.Intent.ACTION_UID_REMOVED;
-import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
import static android.net.TrafficStats.KB_IN_BYTES;
@@ -34,28 +29,42 @@
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.Time.TIMEZONE_UTC;
+
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
-import static org.easymock.EasyMock.anyInt;
-import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.aryEq;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
+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;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
-import android.app.IProcessObserver;
+import android.app.IUidObserver;
import android.app.Notification;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
-import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
@@ -69,40 +78,47 @@
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.IPowerManager;
-import android.os.MessageQueue.IdleHandler;
+import android.os.PowerManagerInternal;
import android.os.UserHandle;
-import android.test.AndroidTestCase;
-import android.test.mock.MockPackageManager;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
import android.text.format.Time;
+import android.util.Log;
import android.util.TrustedTime;
+import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkPolicyManagerService;
+
+import libcore.io.IoUtils;
+
import com.google.common.util.concurrent.AbstractFuture;
-import org.easymock.Capture;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.File;
-import java.util.Calendar;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
-import java.util.TimeZone;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.logging.Handler;
-
-import libcore.io.IoUtils;
/**
* Tests for {@link NetworkPolicyManagerService}.
*/
-@LargeTest
-public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkPolicyManagerServiceTest {
private static final String TAG = "NetworkPolicyManagerServiceTest";
private static final long TEST_START = 1194220800000L;
@@ -114,20 +130,19 @@
private BroadcastInterceptingContext mServiceContext;
private File mPolicyDir;
- private IActivityManager mActivityManager;
- private IPowerManager mPowerManager;
- private INetworkStatsService mStatsService;
- private INetworkManagementService mNetworkManager;
- private INetworkPolicyListener mPolicyListener;
- private TrustedTime mTime;
- private IConnectivityManager mConnManager;
- private INotificationManager mNotifManager;
+ private @Mock IActivityManager mActivityManager;
+ private @Mock INetworkStatsService mStatsService;
+ private @Mock INetworkManagementService mNetworkManager;
+ private @Mock TrustedTime mTime;
+ private @Mock IConnectivityManager mConnManager;
+ private @Mock INotificationManager mNotifManager;
+ private @Mock PackageManager mPackageManager;
- private NetworkPolicyManagerService mService;
- private IProcessObserver mProcessObserver;
+ private IUidObserver mUidObserver;
private INetworkManagementEventObserver mNetworkObserver;
- private Binder mStubBinder = new Binder();
+ private NetworkPolicyListenerAnswer mPolicyListener;
+ private NetworkPolicyManagerService mService;
private long mStartTime;
private long mElapsedRealtime;
@@ -140,39 +155,30 @@
private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
- private static final int PID_1 = 400;
- private static final int PID_2 = 401;
- private static final int PID_3 = 402;
+ private static final String PKG_NAME_A = "name.is.A,pkg.A";
- public void _setUp() throws Exception {
- super.setUp();
+ @BeforeClass
+ public static void registerLocalServices() {
+ addLocalServiceMock(PowerManagerInternal.class);
+ addLocalServiceMock(DeviceIdleController.LocalService.class);
+ final UsageStatsManagerInternal usageStats =
+ addLocalServiceMock(UsageStatsManagerInternal.class);
+ when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
+ }
+
+ @Before
+ public void callSystemReady() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ final Context context = InstrumentationRegistry.getContext();
setCurrentTimeMillis(TEST_START);
// intercept various broadcasts, and pretend that uids have packages
- mServiceContext = new BroadcastInterceptingContext(getContext()) {
+ mServiceContext = new BroadcastInterceptingContext(context) {
@Override
public PackageManager getPackageManager() {
- return new MockPackageManager() {
- @Override
- public String[] getPackagesForUid(int uid) {
- return new String[] { "com.example" };
- }
-
- @Override
- public PackageInfo getPackageInfo(String packageName, int flags) {
- final PackageInfo info = new PackageInfo();
- final Signature signature;
- if ("android".equals(packageName)) {
- signature = new Signature("F00D");
- } else {
- signature = new Signature("DEAD");
- }
- info.signatures = new Signature[] { signature };
- return info;
- }
-
- };
+ return mPackageManager;
}
@Override
@@ -181,275 +187,112 @@
}
};
- mPolicyDir = getContext().getFilesDir();
+ mPolicyDir = context.getFilesDir();
if (mPolicyDir.exists()) {
IoUtils.deleteContents(mPolicyDir);
}
- mActivityManager = createMock(IActivityManager.class);
- mPowerManager = createMock(IPowerManager.class);
- mStatsService = createMock(INetworkStatsService.class);
- mNetworkManager = createMock(INetworkManagementService.class);
- mPolicyListener = createMock(INetworkPolicyListener.class);
- mTime = createMock(TrustedTime.class);
- mConnManager = createMock(IConnectivityManager.class);
- mNotifManager = createMock(INotificationManager.class);
+ doAnswer(new Answer<Void>() {
- mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mPowerManager,
- mStatsService, mNetworkManager, mTime, mPolicyDir, true);
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ mUidObserver = (IUidObserver) invocation.getArguments()[0];
+ Log.d(TAG, "set mUidObserver to " + mUidObserver);
+ return null;
+ }
+ }).when(mActivityManager).registerUidObserver(any(), anyInt());
+
+ mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
+ mNetworkManager, mTime, mPolicyDir, true);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
+ mPolicyListener = new NetworkPolicyListenerAnswer(mService);
- // RemoteCallbackList needs a binder to use as key
- expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
- replay();
- mService.registerListener(mPolicyListener);
- verifyAndReset();
+ // Sets some common expectations.
+ when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
+ new Answer<PackageInfo>() {
- // catch IProcessObserver during systemReady()
- final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
- mActivityManager.registerProcessObserver(capture(processObserver));
- expectLastCall().atLeastOnce();
-
- // catch INetworkManagementEventObserver during systemReady()
- final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
- INetworkManagementEventObserver>();
- mNetworkManager.registerObserver(capture(networkObserver));
- expectLastCall().atLeastOnce();
-
- // expect to answer screen status during systemReady()
- expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
- expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+ @Override
+ public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
+ final String packageName = (String) invocation.getArguments()[0];
+ final PackageInfo info = new PackageInfo();
+ final Signature signature;
+ if ("android".equals(packageName)) {
+ signature = new Signature("F00D");
+ } else {
+ signature = new Signature("DEAD");
+ }
+ info.signatures = new Signature[] {
+ signature
+ };
+ return info;
+ }
+ });
+ when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(new ApplicationInfo());
+ when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
+ when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
expectCurrentTime();
- replay();
+ // Prepare NPMS.
mService.systemReady();
- verifyAndReset();
- mProcessObserver = processObserver.getValue();
+ // catch INetworkManagementEventObserver during systemReady()
+ ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
-
}
- public void _tearDown() throws Exception {
+ @After
+ public void removeFiles() throws Exception {
for (File file : mPolicyDir.listFiles()) {
file.delete();
}
-
- mServiceContext = null;
- mPolicyDir = null;
-
- mActivityManager = null;
- mPowerManager = null;
- mStatsService = null;
- mPolicyListener = null;
- mTime = null;
-
- mService = null;
- mProcessObserver = null;
-
- super.tearDown();
}
- @Suppress
- public void testPolicyChangeTriggersBroadcast() throws Exception {
+ @After
+ public void unregisterLocalServices() throws Exception {
+ // Registered by NetworkPolicyManagerService's constructor.
+ LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
+ }
+
+ // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
+ // don't check for side-effects (like calls to NetworkManagementService) neither cover all
+ // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
+ // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
+
+ @Test
+ public void testPolicyChangeTriggersListener() throws Exception {
+ mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-
- // change background policy and expect broadcast
- final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
- ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
-
mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- backgroundChanged.get();
+ mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
}
- @Suppress
- public void testPidForegroundCombined() throws Exception {
- IdleFuture idle;
-
- // push all uid into background
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
- idle.get();
+ @Test
+ public void testUidForeground() throws Exception {
+ // push all uids into background
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
assertFalse(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
- // push one of the shared pids into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- idle.get();
+ // push one of the uids into foreground
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
- idle.get();
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
assertFalse(mService.isUidForeground(UID_A));
assertTrue(mService.isUidForeground(UID_B));
-
- // push both pid into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- idle.get();
- assertTrue(mService.isUidForeground(UID_A));
-
- // pull one out, should still be foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- idle.get();
- assertTrue(mService.isUidForeground(UID_A));
-
- // pull final pid out, should now be background
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- idle.get();
- assertFalse(mService.isUidForeground(UID_A));
}
- @Suppress
- public void testScreenChangesRules() throws Exception {
- Future<Void> future;
-
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // push strict policy for foreground uid, verify ALLOW rule
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // now turn screen off and verify REJECT rule
- expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
- future.get();
- verifyAndReset();
-
- // and turn screen back on, verify ALLOW rule restored
- expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyNone() throws Exception {
- Future<Void> future;
-
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // POLICY_NONE should RULE_ALLOW in foreground
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
-
- // POLICY_NONE should RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyReject() throws Exception {
- Future<Void> future;
-
- // POLICY_REJECT should RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // POLICY_REJECT should RULE_ALLOW in foreground
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // POLICY_REJECT should RULE_REJECT in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyRejectAddRemove() throws Exception {
- Future<Void> future;
-
- // POLICY_NONE should have RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
-
- // adding POLICY_REJECT should cause RULE_REJECT
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // removing POLICY_REJECT should return us to RULE_ALLOW
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
- }
-
+ @Test
public void testLastCycleBoundaryThisMonth() throws Exception {
// assume cycle day of "5th", which should be in same month
final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -461,6 +304,7 @@
assertTimeEquals(expectedCycle, actualCycle);
}
+ @Test
public void testLastCycleBoundaryLastMonth() throws Exception {
// assume cycle day of "20th", which should be in last month
final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -472,6 +316,7 @@
assertTimeEquals(expectedCycle, actualCycle);
}
+ @Test
public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
// assume cycle day of "30th" in february; should go to january
final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
@@ -483,6 +328,7 @@
assertTimeEquals(expectedCycle, actualCycle);
}
+ @Test
public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
// assume cycle day of "30th" in february, which should clamp
final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
@@ -494,6 +340,7 @@
assertTimeEquals(expectedCycle, actualCycle);
}
+ @Test
public void testCycleBoundaryLeapYear() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false);
@@ -517,6 +364,7 @@
computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
}
+ @Test
public void testNextCycleTimezoneAfterUtc() throws Exception {
// US/Central is UTC-6
final NetworkPolicy policy = new NetworkPolicy(
@@ -525,6 +373,7 @@
computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
}
+ @Test
public void testNextCycleTimezoneBeforeUtc() throws Exception {
// Israel is UTC+2
final NetworkPolicy policy = new NetworkPolicy(
@@ -533,6 +382,7 @@
computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
}
+ @Test
public void testNextCycleSane() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -548,6 +398,7 @@
}
}
+ @Test
public void testLastCycleSane() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -563,6 +414,7 @@
}
}
+ @Test
public void testCycleTodayJanuary() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
@@ -582,6 +434,7 @@
computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
}
+ @Test
public void testLastCycleBoundaryDST() throws Exception {
final long currentTime = parseTime("1989-01-02T07:30:00.000");
final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");
@@ -592,11 +445,10 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Suppress
+ @Test
public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -607,75 +459,40 @@
// first, pretend that wifi network comes online. no policy active,
// which means we shouldn't push limit to interface.
state = new NetworkState[] { buildWifi() };
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
expectCurrentTime();
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged();
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
// now change cycle to be on 15th, and test in early march, to verify we
// pick cycle day in previous month.
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
expectCurrentTime();
// pretend that 512 bytes total have happened
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+ .thenReturn(stats.getTotalBytes());
- // TODO: consider making strongly ordered mock
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ // TODO: consider making strongly ordered mock
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
}
- @Suppress
- public void testUidRemovedPolicyCleared() throws Exception {
- Future<Void> future;
-
- // POLICY_REJECT should RULE_REJECT in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // uninstall should clear RULE_REJECT
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- final Intent intent = new Intent(ACTION_UID_REMOVED);
- intent.putExtra(EXTRA_UID, UID_A);
- mServiceContext.sendBroadcast(intent);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
+ @Test
public void testOverWarningLimitNotification() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
- Future<String> tagFuture;
+ Future<String> tagFuture = null;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -690,20 +507,15 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged();
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
* MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+ verifyPolicyDataEnable(TYPE_WIFI, true);
}
// bring up wifi network
@@ -714,22 +526,17 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
}
// go over warning, which should kick notification
@@ -739,18 +546,15 @@
{
expectCurrentTime();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
-
- expectForceUpdate();
- expectClearNotifications();
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
+
assertNotificationType(TYPE_WARNING, tagFuture.get());
- verifyAndReset();
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+
}
// go over limit, which should kick notification and dialog
@@ -760,18 +564,14 @@
{
expectCurrentTime();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, false);
-
- expectForceUpdate();
- expectClearNotifications();
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
+
assertNotificationType(TYPE_LIMIT, tagFuture.get());
- verifyAndReset();
+ verifyPolicyDataEnable(TYPE_WIFI, false);
}
// now snooze policy, which should remove quota
@@ -779,35 +579,28 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
-
- // snoozed interface still has high quota so background data is
- // still restricted.
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
- expectAdvisePersistThreshold();
- expectMeteredIfacesChanged(TEST_IFACE);
-
- future = expectClearNotifications();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mService.snoozeLimit(sTemplateWifi);
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
- future.get();
- verifyAndReset();
+ // snoozed interface still has high quota so background data is
+ // still restricted.
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+ verifyPolicyDataEnable(TYPE_WIFI, true);
}
}
- @Suppress
+ @Test
public void testMeteredNetworkWithoutLimit() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
- Future<String> tagFuture;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -822,24 +615,19 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
true));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
}
}
@@ -862,87 +650,36 @@
}
private void expectCurrentTime() throws Exception {
- expect(mTime.forceRefresh()).andReturn(false).anyTimes();
- expect(mTime.hasCache()).andReturn(true).anyTimes();
- expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
- expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
- expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
- }
-
- private void expectForceUpdate() throws Exception {
- mStatsService.forceUpdate();
- expectLastCall().atLeastOnce();
- }
-
- private Future<Void> expectClearNotifications() throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mNotifManager.cancelNotificationWithTag(
- isA(String.class), isA(String.class), anyInt(), anyInt());
- expectLastCall().andAnswer(future).anyTimes();
- return future;
+ when(mTime.forceRefresh()).thenReturn(false);
+ when(mTime.hasCache()).thenReturn(true);
+ when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
+ when(mTime.getCacheAge()).thenReturn(0L);
+ when(mTime.getCacheCertainty()).thenReturn(0L);
}
private Future<String> expectEnqueueNotification() throws Exception {
- final FutureCapture<String> tag = new FutureCapture<String>();
- mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
- capture(tag.capture), anyInt(),
- isA(Notification.class), isA(int[].class), UserHandle.myUserId());
- return tag;
+ final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
+ doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
+ anyString(), anyString(), anyString() /* capture here (index 2)*/,
+ anyInt(), isA(Notification.class), isA(int[].class), anyInt());
+ return futureAnswer;
}
- private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
- mNetworkManager.setInterfaceQuota(iface, quotaBytes);
- expectLastCall().atLeastOnce();
+ private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+ verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
}
- private void expectRemoveInterfaceQuota(String iface) throws Exception {
- mNetworkManager.removeInterfaceQuota(iface);
- expectLastCall().atLeastOnce();
+ private void verifyRemoveInterfaceQuota(String iface) throws Exception {
+ verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
}
- private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
- mNetworkManager.setInterfaceAlert(iface, alertBytes);
- expectLastCall().atLeastOnce();
- }
-
- private void expectRemoveInterfaceAlert(String iface) throws Exception {
- mNetworkManager.removeInterfaceAlert(iface);
- expectLastCall().atLeastOnce();
- }
-
- private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
- throws Exception {
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
- expectLastCall().atLeastOnce();
- }
-
- private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
- mStatsService.setUidForeground(uid, uidForeground);
- expectLastCall().atLeastOnce();
- }
-
- private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
- expectLastCall().andAnswer(future);
- return future;
- }
-
- private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
- expectLastCall().andAnswer(future);
- return future;
- }
-
- private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
+ private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
// TODO: bring back this test
return null;
}
- private void expectAdvisePersistThreshold() throws Exception {
- mStatsService.advisePersistThreshold(anyLong());
- expectLastCall().anyTimes();
+ private void verifyAdvisePersistThreshold() throws Exception {
+ verify(mStatsService).advisePersistThreshold(anyLong());
}
private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -956,50 +693,21 @@
}
}
- private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
+ private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
+ private final int index;
+
+ FutureAnswer(int index) {
+ this.index = index;
+ }
@Override
- public Void answer() {
- set(null);
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ @SuppressWarnings("unchecked")
+ T captured = (T) invocation.getArguments()[index];
+ set(captured);
return null;
}
}
- private static class FutureCapture<T> extends TestAbstractFuture<T> {
- public Capture<T> capture = new Capture<T>() {
- @Override
- public void setValue(T value) {
- super.setValue(value);
- set(value);
- }
- };
- }
-
- private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
- @Override
- public Void get() throws InterruptedException, ExecutionException {
- try {
- return get(5, TimeUnit.SECONDS);
- } catch (TimeoutException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public boolean queueIdle() {
- set(null);
- return false;
- }
- }
-
- /**
- * Wait until {@link #mService} internal {@link Handler} is idle.
- */
- private IdleFuture expectIdle() {
- final IdleFuture future = new IdleFuture();
- mService.addIdleHandler(future);
- return future;
- }
-
private static void assertTimeEquals(long expected, long actual) {
if (expected != actual) {
fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -1027,7 +735,7 @@
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals(
+ assertEquals("notification type mismatch for '" + actualTag +"'",
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -1048,15 +756,59 @@
mElapsedRealtime += duration;
}
- private void replay() {
- EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManager, mTime, mConnManager, mNotifManager);
+ /**
+ * Creates a mock and registers it to {@link LocalServices}.
+ */
+ private static <T> T addLocalServiceMock(Class<T> clazz) {
+ final T mock = mock(clazz);
+ LocalServices.addService(clazz, mock);
+ return mock;
}
- private void verifyAndReset() {
- EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManager, mTime, mConnManager, mNotifManager);
- EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManager, mTime, mConnManager, mNotifManager);
+ /**
+ * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
+ *
+ * <p>Typical usage:
+ * <pre><code>
+ * mPolicyListener.expect().someCallback(any());
+ * // do something on objects under test
+ * mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
+ * </code></pre>
+ */
+ final class NetworkPolicyListenerAnswer implements Answer<Void> {
+ private CountDownLatch latch;
+ private final INetworkPolicyListener listener;
+
+ NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
+ this.listener = mock(INetworkPolicyListener.class);
+ // RemoteCallbackList needs a binder to use as key
+ when(listener.asBinder()).thenReturn(new Binder());
+ service.registerListener(listener);
+ }
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Log.d(TAG,"counting down on answer: " + invocation);
+ latch.countDown();
+ return null;
+ }
+
+ INetworkPolicyListener expect() {
+ assertNull("expect() called before waitAndVerify()", latch);
+ latch = new CountDownLatch(1);
+ return doAnswer(this).when(listener);
+ }
+
+ INetworkPolicyListener waitAndVerify() {
+ assertNotNull("waitAndVerify() called before expect()", latch);
+ try {
+ assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ fail("Thread interrupted before callback called");
+ } finally {
+ latch = null;
+ }
+ return verify(listener, atLeastOnce());
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index e7f3345..1c7a138 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -247,20 +247,6 @@
}
@Override
- protected boolean isUserUnlockedL(@UserIdInt int userId) {
- // Note due to a late change, now ShortcutManager doesn't use
- // UserManager.isUserUnlockingOrUnlocked(). But all unit tests are still using it,
- // so we convert here.
-
- final long token = injectClearCallingIdentity();
- try {
- return mMockUserManager.isUserUnlockingOrUnlocked(userId);
- } finally {
- injectRestoreCallingIdentity(token);
- }
- }
-
- @Override
int injectDipToPixel(int dip) {
return dip;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index ba83be1..64c5622 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -39,7 +39,7 @@
public PackageSetting generateFakePackageSetting(String name) {
return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"),
new File(mContext.getCacheDir(), "fakeResPath"), "", "", "",
- "", 1, 0, 0, null, null);
+ "", 1, 0, 0, null, null, 0 /*sharedUserId*/);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index a939134..09bd12c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -522,7 +522,8 @@
pkgFlags,
0 /*privateFlags*/,
null /*parentPackageName*/,
- null /*childPackageNames*/);
+ null /*childPackageNames*/,
+ 0 /*sharedUserId*/);
}
private @NonNull List<UserInfo> createFakeUsers() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 75a3427..253334e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -5863,6 +5863,7 @@
assertEmpty(mManager.getPinnedShortcuts());
});
// Send add broadcast, but the user is not running, so should be ignored.
+ mService.handleCleanupUser(USER_10);
mRunningUsers.put(USER_10, false);
mUnlockedUsers.put(USER_10, false);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index ad5bc77..d25923c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -2005,4 +2005,36 @@
});
});
}
+
+ public void testIsUserUnlocked() {
+ mRunningUsers.clear();
+ mUnlockedUsers.clear();
+
+ assertFalse(mService.isUserUnlockedL(USER_0));
+ assertFalse(mService.isUserUnlockedL(USER_10));
+
+ // Start user 0, still locked.
+ mRunningUsers.put(USER_0, true);
+ assertFalse(mService.isUserUnlockedL(USER_0));
+ assertFalse(mService.isUserUnlockedL(USER_10));
+
+ // Unlock user.
+ mUnlockedUsers.put(USER_0, true);
+ assertTrue(mService.isUserUnlockedL(USER_0));
+ assertFalse(mService.isUserUnlockedL(USER_10));
+
+ // Clear again.
+ mRunningUsers.clear();
+ mUnlockedUsers.clear();
+
+ // Directly call the lifecycle event. Now also locked.
+ mService.handleUnlockUser(USER_0);
+ assertTrue(mService.isUserUnlockedL(USER_0));
+ assertFalse(mService.isUserUnlockedL(USER_10));
+
+ // Directly call the stop lifecycle event. Goes back to the initial state.
+ mService.handleCleanupUser(USER_0);
+ assertFalse(mService.isUserUnlockedL(USER_0));
+ assertFalse(mService.isUserUnlockedL(USER_10));
+ }
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8560651..efd479f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -563,6 +563,7 @@
mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
if (mConfigured && enteringAccessoryMode) {
+ mAccessoryModeRequestTime = 0;
// successfully entered accessory mode
if (mAccessoryStrings != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index b0cc2ac..c3075b3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -46,6 +46,7 @@
import android.view.IWindowManager;
import android.view.WindowManager;
+import com.android.internal.app.AssistUtils;
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
@@ -301,7 +302,7 @@
} else {
mScreenshot = null;
}
- if (needDisclosure) {
+ if (needDisclosure && AssistUtils.shouldDisclose(mContext, mSessionComponentName)) {
mHandler.post(mShowAssistDisclosureRunnable);
}
if (mSession != null) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 68a6166..e666986 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -906,6 +906,19 @@
public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL =
"enhanced_4g_lte_title_variant_bool";
+ /**
+ * Indicates whether the carrier wants to notify the user when handover of an LTE video call to
+ * WIFI fails.
+ * <p>
+ * When {@code true}, if a video call starts on LTE and the modem reports a failure to handover
+ * the call to WIFI or if no handover success is reported within 60 seconds of call initiation,
+ * the {@link android.telephony.TelephonyManager#EVENT_HANDOVER_TO_WIFI_FAILED} event is raised
+ * on the connection.
+ * @hide
+ */
+ public static final String KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL =
+ "notify_vt_handover_to_wifi_failure_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1071,6 +1084,7 @@
sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false);
+ sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index d7d4e84..f5e422d 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -212,6 +212,20 @@
*/
public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53;
+ /**
+ * The call was terminated because cellular data has been disabled.
+ * Used when in a video call and the user disables cellular data via the settings.
+ * {@hide}
+ */
+ public static final int DATA_DISABLED = 54;
+
+ /**
+ * The call was terminated because the data policy has disabled cellular data.
+ * Used when in a video call and the user has exceeded the device data limit.
+ * {@hide}
+ */
+ public static final int DATA_LIMIT_REACHED = 55;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -220,14 +234,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 54
+ // NextId: 56
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = MAXIMUM_NUMBER_OF_CALLS_REACHED;
+ public static final int MAXIMUM_VALID_VALUE = DATA_LIMIT_REACHED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -343,6 +357,10 @@
return "ANSWERED_ELSEWHERE";
case MAXIMUM_NUMBER_OF_CALLS_REACHED:
return "MAXIMUM_NUMER_OF_CALLS_REACHED";
+ case DATA_DISABLED:
+ return "DATA_DISABLED";
+ case DATA_LIMIT_REACHED:
+ return "DATA_LIMIT_REACHED";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fed9e71..4138aa0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2484,6 +2484,56 @@
}
/**
+ * Enables or disables the visual voicemail client for a phone account.
+ *
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
+ * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+ * @see #hasCarrierPrivileges
+ *
+ * @param phoneAccountHandle the phone account to change the client state
+ * @param enabled the new state of the client
+ * @hide
+ */
+ @SystemApi
+ public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.setVisualVoicemailEnabled(mContext.getOpPackageName(), phoneAccountHandle,
+ enabled);
+ }
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ // This could happen before phone restarts due to crashing
+ }
+ }
+
+ /**
+ * Returns whether the visual voicemail client is enabled.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @param phoneAccountHandle the phone account to check for.
+ * @return {@code true} when the visual voicemail client is enabled for this client
+ * @hide
+ */
+ @SystemApi
+ public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isVisualVoicemailEnabled(
+ mContext.getOpPackageName(), phoneAccountHandle);
+ }
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ // This could happen before phone restarts due to crashing
+ }
+ return false;
+ }
+
+ /**
* Enables the visual voicemail SMS filter for a phone account. When the filter is
* enabled, Incoming SMS messages matching the OMTP VVM SMS interface will be redirected to the
* visual voicemail client with
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 408ad31..56b8822 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -298,6 +298,16 @@
public static final int CODE_REMOTE_CALL_DECLINE = 1404;
/**
+ * Indicates the call was disconnected due to the user reaching their data limit.
+ */
+ public static final int CODE_DATA_LIMIT_REACHED = 1405;
+
+ /**
+ * Indicates the call was disconnected due to the user disabling cellular data.
+ */
+ public static final int CODE_DATA_DISABLED = 1406;
+
+ /**
* Network string error messages.
* mExtraMessage may have these values.
*/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 7e7071e..a8eaf36 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -454,6 +454,12 @@
*/
int getVoiceMessageCountForSubscriber(int subId);
+ oneway void setVisualVoicemailEnabled(String callingPackage,
+ in PhoneAccountHandle accountHandle, boolean enabled);
+
+ boolean isVisualVoicemailEnabled(String callingPackage,
+ in PhoneAccountHandle accountHandle);
+
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
in VisualVoicemailSmsFilterSettings settings);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index c1cfd0b..3c3edda 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1309,8 +1309,8 @@
status_t AaptAssets::filter(Bundle* bundle)
{
- WeakResourceFilter reqFilter;
- status_t err = reqFilter.parse(bundle->getConfigurations());
+ sp<WeakResourceFilter> reqFilter(new WeakResourceFilter());
+ status_t err = reqFilter->parse(bundle->getConfigurations());
if (err != NO_ERROR) {
return err;
}
@@ -1326,12 +1326,12 @@
preferredDensity = preferredConfig.density;
}
- if (reqFilter.isEmpty() && preferredDensity == 0) {
+ if (reqFilter->isEmpty() && preferredDensity == 0) {
return NO_ERROR;
}
if (bundle->getVerbose()) {
- if (!reqFilter.isEmpty()) {
+ if (!reqFilter->isEmpty()) {
printf("Applying required filter: %s\n",
bundle->getConfigurations().string());
}
@@ -1383,7 +1383,7 @@
continue;
}
const ResTable_config& config(file->getGroupEntry().toParams());
- if (!reqFilter.match(config)) {
+ if (!reqFilter->match(config)) {
if (bundle->getVerbose()) {
printf("Pruning unneeded resource: %s\n",
file->getPrintableSource().string());
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 4fdc964..eadd48a 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -103,7 +103,7 @@
{
public:
AaptGroupEntry() {}
- AaptGroupEntry(const ConfigDescription& config) : mParams(config) {}
+ explicit AaptGroupEntry(const ConfigDescription& config) : mParams(config) {}
bool initFromDirName(const char* dir, String8* resType);
@@ -312,7 +312,7 @@
: isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
{
}
- AaptSymbolEntry(const String8& _name)
+ explicit AaptSymbolEntry(const String8& _name)
: name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
{
}
diff --git a/tools/aapt/ApkBuilder.h b/tools/aapt/ApkBuilder.h
index 0d7f06b..5d3abc6 100644
--- a/tools/aapt/ApkBuilder.h
+++ b/tools/aapt/ApkBuilder.h
@@ -32,7 +32,7 @@
class ApkBuilder : public android::RefBase {
public:
- ApkBuilder(const sp<WeakResourceFilter>& configFilter);
+ explicit ApkBuilder(const sp<WeakResourceFilter>& configFilter);
/**
* Tells the builder to generate a separate APK for resources that
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
index 10a1bbc..6fa96d6 100644
--- a/tools/aapt/CacheUpdater.h
+++ b/tools/aapt/CacheUpdater.h
@@ -51,7 +51,7 @@
class SystemCacheUpdater : public CacheUpdater {
public:
// Constructor to set bundle to pass to preProcessImage
- SystemCacheUpdater (Bundle* b)
+ explicit SystemCacheUpdater (Bundle* b)
: bundle(b) { };
// Make sure all the directories along this path exist
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cbad4b9..d80aaba 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -248,7 +248,7 @@
}
static void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
- uint32_t attrRes, String8 attrLabel, String8* outError)
+ uint32_t attrRes, const String8& attrLabel, String8* outError)
{
Res_value value;
AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
@@ -399,7 +399,7 @@
ResTable::normalizeForOutput(reason.string()).string());
}
-Vector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
+Vector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost,
String8 *outError = NULL)
{
Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h
index 4f999a2..09430f2 100644
--- a/tools/aapt/ConfigDescription.h
+++ b/tools/aapt/ConfigDescription.h
@@ -29,7 +29,7 @@
size = sizeof(android::ResTable_config);
}
- ConfigDescription(const android::ResTable_config&o) {
+ ConfigDescription(const android::ResTable_config&o) { // NOLINT(implicit)
*static_cast<android::ResTable_config*>(this) = o;
size = sizeof(android::ResTable_config);
}
diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp
index 0d574cf..7b8a576 100644
--- a/tools/aapt/CrunchCache.cpp
+++ b/tools/aapt/CrunchCache.cpp
@@ -94,7 +94,7 @@
delete dw;
}
-bool CrunchCache::needsUpdating(String8 relativePath) const
+bool CrunchCache::needsUpdating(const String8& relativePath) const
{
// Retrieve modification dates for this file entry under the source and
// cache directory trees. The vectors will return a modification date of 0
diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h
index be3da5c..4d6a169 100644
--- a/tools/aapt/CrunchCache.h
+++ b/tools/aapt/CrunchCache.h
@@ -81,7 +81,7 @@
* // Recrunch sourceFile out to destFile.
*
*/
- bool needsUpdating(String8 relativePath) const;
+ bool needsUpdating(const String8& relativePath) const;
// DATA MEMBERS ====================================================
diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp
index 18775c0..c9d0744 100644
--- a/tools/aapt/FileFinder.cpp
+++ b/tools/aapt/FileFinder.cpp
@@ -77,7 +77,7 @@
return true;
}
-void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
+void SystemFileFinder::checkAndAddFile(const String8& path, const struct stat* stats,
Vector<String8>& extensions,
KeyedVector<String8,time_t>& fileStore)
{
diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h
index 6974aee..f405381 100644
--- a/tools/aapt/FileFinder.h
+++ b/tools/aapt/FileFinder.h
@@ -72,7 +72,7 @@
* time as the value.
*
*/
- static void checkAndAddFile(String8 path, const struct stat* stats,
+ static void checkAndAddFile(const String8& path, const struct stat* stats,
Vector<String8>& extensions,
KeyedVector<String8,time_t>& fileStore);
diff --git a/tools/aapt/IndentPrinter.h b/tools/aapt/IndentPrinter.h
index 6fc94bc..bd0edcb 100644
--- a/tools/aapt/IndentPrinter.h
+++ b/tools/aapt/IndentPrinter.h
@@ -3,7 +3,7 @@
class IndentPrinter {
public:
- IndentPrinter(FILE* stream, int indentSize=2)
+ explicit IndentPrinter(FILE* stream, int indentSize=2)
: mStream(stream)
, mIndentSize(indentSize)
, mIndent(0)
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index b278831..b4c4d05 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -399,7 +399,7 @@
const DefaultKeyedVector<String8, sp<AaptGroup> >& groups = dir->getFiles();
int N = groups.size();
for (int i=0; i<N; i++) {
- String8 leafName = groups.keyAt(i);
+ const String8& leafName = groups.keyAt(i);
const sp<AaptGroup>& group = groups.valueAt(i);
const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files
@@ -422,7 +422,7 @@
set->add(leafName, group);
resources->add(resType, set);
} else {
- sp<ResourceTypeSet> set = resources->valueAt(index);
+ const sp<ResourceTypeSet>& set = resources->valueAt(index);
index = set->indexOfKey(leafName);
if (index < 0) {
if (kIsDebug) {
@@ -457,7 +457,7 @@
int N = dirs.size();
for (int i=0; i<N; i++) {
- sp<AaptDir> d = dirs.itemAt(i);
+ const sp<AaptDir>& d = dirs.itemAt(i);
if (kIsDebug) {
printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(),
d->getLeaf().string());
@@ -615,7 +615,7 @@
// get the overlay resources of the requested type
ssize_t index = overlayRes->indexOfKey(resTypeString);
if (index >= 0) {
- sp<ResourceTypeSet> overlaySet = overlayRes->valueAt(index);
+ const sp<ResourceTypeSet>& overlaySet = overlayRes->valueAt(index);
// for each of the resources, check for a match in the previously built
// non-overlay "baseset".
@@ -765,7 +765,7 @@
return addTagAttribute(node, ns8, attr8, value, errorOnFailedInsert, false);
}
-static void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
+static void fullyQualifyClassName(const String8& package, const sp<XMLNode>& node,
const String16& attrName) {
XMLNode::attribute_entry* attr = node->editAttribute(
String16("http://schemas.android.com/apk/res/android"), attrName);
@@ -1350,7 +1350,7 @@
ResourceDirIterator it(resources->valueAt(index), String8("values"));
ssize_t res;
while ((res=it.next()) == NO_ERROR) {
- sp<AaptFile> file = it.getFile();
+ const sp<AaptFile>& file = it.getFile();
res = compileResourceFile(bundle, assets, file, it.getParams(),
(current!=assets), &table);
if (res != NO_ERROR) {
@@ -2688,7 +2688,7 @@
String8 dest(bundle->getRClassDir());
if (bundle->getMakePackageDirs()) {
- String8 pkg(package);
+ const String8& pkg(package);
const char* last = pkg.string();
const char* s = last-1;
do {
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index d6430c0..40d5b75 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -78,7 +78,7 @@
class StrongResourceFilter : public ResourceFilter {
public:
StrongResourceFilter() {}
- StrongResourceFilter(const std::set<ConfigDescription>& configs)
+ explicit StrongResourceFilter(const std::set<ConfigDescription>& configs)
: mConfigs(configs) {}
android::status_t parse(const android::String8& str);
@@ -106,7 +106,7 @@
*/
class InverseResourceFilter : public ResourceFilter {
public:
- InverseResourceFilter(const android::sp<ResourceFilter>& filter)
+ explicit InverseResourceFilter(const android::sp<ResourceFilter>& filter)
: mFilter(filter) {}
bool match(const android::ResTable_config& config) const {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 4d5bb31..76c59dd 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4081,7 +4081,7 @@
j = 0;
for (i=0; i<N; i++) {
- sp<ConfigList> e = origOrder.itemAt(i);
+ const sp<ConfigList>& e = origOrder.itemAt(i);
// There will always be enough room for the remaining entries.
while (mOrderedConfigs.itemAt(j) != NULL) {
j++;
@@ -4203,7 +4203,7 @@
size_t j=0;
for (i=0; i<N; i++) {
- sp<Type> t = origOrder.itemAt(i);
+ const sp<Type>& t = origOrder.itemAt(i);
// There will always be enough room for the remaining types.
while (mOrderedTypes.itemAt(j) != NULL) {
j++;
@@ -4636,7 +4636,7 @@
c->getEntries();
const size_t entryCount = entries.size();
for (size_t ei = 0; ei < entryCount; ei++) {
- sp<Entry> e = entries.valueAt(ei);
+ const sp<Entry>& e = entries.valueAt(ei);
if (e == NULL || e->getType() != Entry::TYPE_BAG) {
continue;
}
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 4b0d920..625b0bf 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -41,7 +41,7 @@
public:
struct entry {
entry() : offset(0) { }
- entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
+ explicit entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
entry(const entry& o) : value(o.value), offset(o.offset),
hasStyles(o.hasStyles), indices(o.indices),
configTypeName(o.configTypeName), configs(o.configs) { }
diff --git a/tools/aapt/WorkQueue.h b/tools/aapt/WorkQueue.h
index d38f05d..ab5f969 100644
--- a/tools/aapt/WorkQueue.h
+++ b/tools/aapt/WorkQueue.h
@@ -47,7 +47,7 @@
};
/* Creates a work queue with the specified maximum number of work threads. */
- WorkQueue(size_t maxThreads, bool canCallJava = true);
+ explicit WorkQueue(size_t maxThreads, bool canCallJava = true);
/* Destroys the work queue.
* Cancels pending work and waits for all remaining threads to complete.
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 5b215da..15ec4af 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -67,7 +67,7 @@
static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools");
-String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic)
+String16 getNamespaceResourcePackage(const String16& appPackage, const String16& namespaceUri, bool* outIsPublic)
{
//printf("%s starts with %s?\n", String8(namespaceUri).string(),
// String8(RESOURCES_PREFIX).string());
@@ -98,7 +98,7 @@
status_t hasSubstitutionErrors(const char* fileName,
ResXMLTree* inXml,
- String16 str16)
+ const String16& str16)
{
const char16_t* str = str16.string();
const char16_t* p = str;
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 749bf9f..ac92018 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -178,7 +178,7 @@
XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace);
// Creating a CDATA node.
- XMLNode(const String8& filename);
+ explicit XMLNode(const String8& filename);
status_t collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
bool stripComments, bool stripRawValues) const;
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
index 1faecd1..9bb1fd8 100644
--- a/tools/aapt/pseudolocalize.h
+++ b/tools/aapt/pseudolocalize.h
@@ -43,7 +43,7 @@
class Pseudolocalizer {
public:
- Pseudolocalizer(PseudolocalizationMethod m);
+ explicit Pseudolocalizer(PseudolocalizationMethod m);
~Pseudolocalizer() { if (mImpl) delete mImpl; }
void setMethod(PseudolocalizationMethod m);
String16 start() { return mImpl->start(); }
diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h
index ef0d147..6858c62 100644
--- a/tools/aapt2/ConfigDescription.h
+++ b/tools/aapt2/ConfigDescription.h
@@ -51,7 +51,7 @@
static void applyVersionForCompatibility(ConfigDescription* config);
ConfigDescription();
- ConfigDescription(const android::ResTable_config& o);
+ ConfigDescription(const android::ResTable_config& o); // NOLINT(implicit)
ConfigDescription(const ConfigDescription& o);
ConfigDescription(ConfigDescription&& o);
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 0ba0345..09a04e0 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -100,7 +100,7 @@
ResourceNameRef() = default;
ResourceNameRef(const ResourceNameRef&) = default;
ResourceNameRef(ResourceNameRef&&) = default;
- ResourceNameRef(const ResourceName& rhs);
+ ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit)
ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e);
ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
@@ -126,7 +126,7 @@
ResourceId();
ResourceId(const ResourceId& rhs);
- ResourceId(uint32_t resId);
+ ResourceId(uint32_t resId); // NOLINT(implicit)
ResourceId(uint8_t p, uint8_t t, uint16_t e);
bool isValid() const;
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 4d418d9..460de0e 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -274,7 +274,7 @@
}
bool ResourceTable::addResource(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
@@ -325,7 +325,7 @@
}
bool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name,
- const ResourceId id,
+ const ResourceId& id,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
@@ -335,12 +335,12 @@
}
bool ResourceTable::addResourceImpl(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
const char* validChars,
- std::function<int(Value*,Value*)> conflictResolver,
+ const std::function<int(Value*,Value*)>& conflictResolver,
IDiagnostics* diag) {
assert(value && "value can't be nullptr");
assert(diag && "diagnostics can't be nullptr");
@@ -426,18 +426,18 @@
return true;
}
-bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId resId,
+bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId& resId,
const Symbol& symbol, IDiagnostics* diag) {
return setSymbolStateImpl(name, resId, symbol, kValidNameChars, diag);
}
bool ResourceTable::setSymbolStateAllowMangled(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol, IDiagnostics* diag) {
return setSymbolStateImpl(name, resId, symbol, kValidNameMangledChars, diag);
}
-bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId,
+bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId& resId,
const Symbol& symbol, const char* validChars,
IDiagnostics* diag) {
assert(diag && "diagnostics can't be nullptr");
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index a5efe35..6b52a43 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -103,7 +103,7 @@
*/
std::vector<std::unique_ptr<ResourceConfigValue>> values;
- ResourceEntry(const StringPiece& name) : name(name.toString()) { }
+ explicit ResourceEntry(const StringPiece& name) : name(name.toString()) { }
ResourceConfigValue* findValue(const ConfigDescription& config);
ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product);
@@ -200,7 +200,7 @@
IDiagnostics* diag);
bool addResource(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
@@ -231,19 +231,19 @@
IDiagnostics* diag);
bool addResourceAllowMangled(const ResourceNameRef& name,
- const ResourceId id,
+ const ResourceId& id,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
IDiagnostics* diag);
bool setSymbolState(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol,
IDiagnostics* diag);
bool setSymbolStateAllowMangled(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol,
IDiagnostics* diag);
@@ -294,16 +294,16 @@
IDiagnostics* diag);
bool addResourceImpl(const ResourceNameRef& name,
- ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
const char* validChars,
- std::function<int(Value*,Value*)> conflictResolver,
+ const std::function<int(Value*,Value*)>& conflictResolver,
IDiagnostics* diag);
bool setSymbolStateImpl(const ResourceNameRef& name,
- ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol,
const char* validChars,
IDiagnostics* diag);
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 7dc88ded..773616d 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -545,7 +545,7 @@
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& value,
uint32_t typeMask,
- std::function<void(const ResourceName&)> onCreateReference) {
+ const std::function<void(const ResourceName&)>& onCreateReference) {
std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value);
if (nullOrEmpty) {
return std::move(nullOrEmpty);
@@ -604,7 +604,7 @@
*/
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& str, const Attribute* attr,
- std::function<void(const ResourceName&)> onCreateReference) {
+ const std::function<void(const ResourceName&)>& onCreateReference) {
const uint32_t typeMask = attr->typeMask;
std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference);
if (value) {
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 31b8e89..a57d89d 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -163,11 +163,11 @@
*/
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& value, const Attribute* attr,
- std::function<void(const ResourceName&)> onCreateReference = {});
+ const std::function<void(const ResourceName&)>& onCreateReference = {});
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& value, uint32_t typeMask,
- std::function<void(const ResourceName&)> onCreateReference = {});
+ const std::function<void(const ResourceName&)>& onCreateReference = {});
uint32_t androidTypeToAttributeTypeMask(uint16_t type);
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 8ae71ad..e6af716 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -198,7 +198,7 @@
struct RawString : public BaseItem<RawString> {
StringPool::Ref value;
- RawString(const StringPool::Ref& ref);
+ explicit RawString(const StringPool::Ref& ref);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -209,7 +209,7 @@
struct String : public BaseItem<String> {
StringPool::Ref value;
- String(const StringPool::Ref& ref);
+ explicit String(const StringPool::Ref& ref);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -220,7 +220,7 @@
struct StyledString : public BaseItem<StyledString> {
StringPool::StyleRef value;
- StyledString(const StringPool::StyleRef& ref);
+ explicit StyledString(const StringPool::StyleRef& ref);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -237,7 +237,7 @@
io::IFile* file = nullptr;
FileReference() = default;
- FileReference(const StringPool::Ref& path);
+ explicit FileReference(const StringPool::Ref& path);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -252,7 +252,7 @@
android::Res_value value;
BinaryPrimitive() = default;
- BinaryPrimitive(const android::Res_value& val);
+ explicit BinaryPrimitive(const android::Res_value& val);
BinaryPrimitive(uint8_t dataType, uint32_t data);
bool equals(const Value* value) const override;
@@ -272,7 +272,7 @@
int32_t maxInt;
std::vector<Symbol> symbols;
- Attribute(bool w, uint32_t t = 0u);
+ explicit Attribute(bool w, uint32_t t = 0u);
bool equals(const Value* value) const override;
Attribute* clone(StringPool* newPool) const override;
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 91e755d..ccf0383 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -52,7 +52,7 @@
return p.first < entryId;
}
-size_t findAttributeSdkLevel(ResourceId id) {
+size_t findAttributeSdkLevel(const ResourceId& id) {
if (id.packageId() != 0x01 && id.typeId() != 0x01) {
return 0;
}
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index f28679f..c9dbdca 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -47,7 +47,7 @@
SDK_MARSHMALLOW = 23,
};
-size_t findAttributeSdkLevel(ResourceId id);
+size_t findAttributeSdkLevel(const ResourceId& id);
size_t findAttributeSdkLevel(const ResourceName& name);
std::pair<StringPiece, int> getDevelopmentSdkCodeNameAndVersion();
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 72ae9d1..13545be 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -65,7 +65,7 @@
private:
friend class StringPool;
- Ref(Entry* entry);
+ explicit Ref(Entry* entry);
Entry* mEntry;
};
@@ -88,7 +88,7 @@
private:
friend class StringPool;
- StyleRef(StyleEntry* entry);
+ explicit StyleRef(StyleEntry* entry);
StyleEntry* mEntry;
};
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index 501ae9d..4a3f1e1 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -28,7 +28,7 @@
* Assigns the intended ID to the ResourceTablePackage, ResourceTableType, and ResourceEntry,
* as long as there is no existing ID or the ID is the same.
*/
-static bool assignId(IDiagnostics* diag, const ResourceId id, const ResourceName& name,
+static bool assignId(IDiagnostics* diag, const ResourceId& id, const ResourceName& name,
ResourceTablePackage* pkg, ResourceTableType* type, ResourceEntry* entry) {
if (pkg->id.value() == id.packageId()) {
if (!type->id || type->id.value() == id.typeId()) {
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index 0b92ba5..b25bfa7 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -64,7 +64,7 @@
::testing::AssertionResult exists(ResTable* table,
const StringPiece& expectedName,
- const ResourceId expectedId,
+ const ResourceId& expectedId,
const ConfigDescription& expectedConfig,
const uint8_t expectedDataType, const uint32_t expectedData,
const uint32_t expectedSpecFlags) {
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index d26f2e4..4d1e178 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -43,7 +43,7 @@
}
::testing::AssertionResult flatten(xml::XmlResource* doc, android::ResXMLTree* outTree,
- XmlFlattenerOptions options = {}) {
+ const XmlFlattenerOptions& options = {}) {
using namespace android; // For NO_ERROR on windows because it is a macro.
BigBuffer buffer(1024);
diff --git a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
index b6d8f2d..1156b01 100644
--- a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
+++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
@@ -14,4 +14,7 @@
limitations under the License.
-->
-<manifest package="com.android.aapt.app.one" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.aapt.app.one" coreApp="true">
+ <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 45472ff..ff777a3 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -528,7 +528,7 @@
static bool writeStableIdMapToPath(IDiagnostics* diag,
const std::unordered_map<ResourceName, ResourceId>& idMap,
- const std::string idMapPath) {
+ const std::string& idMapPath) {
std::ofstream fout(idMapPath, std::ofstream::binary);
if (!fout) {
diag->error(DiagMessage(idMapPath) << strerror(errno));
@@ -823,7 +823,7 @@
}
bool writeJavaFile(ResourceTable* table, const StringPiece& packageNameToGenerate,
- const StringPiece& outPackage, JavaClassGeneratorOptions javaOptions) {
+ const StringPiece& outPackage, const JavaClassGeneratorOptions& javaOptions) {
if (!mOptions.generateJavaClassPath) {
return true;
}
@@ -1191,6 +1191,12 @@
mContext->getDiagnostics())) {
AppInfo& appInfo = maybeAppInfo.value();
mContext->setCompilationPackage(appInfo.package);
+ if (appInfo.minSdkVersion) {
+ if (Maybe<int> maybeMinSdkVersion =
+ ResourceUtils::tryParseSdkVersion(appInfo.minSdkVersion.value())) {
+ mContext->setMinSdkVersion(maybeMinSdkVersion.value());
+ }
+ }
} else {
return 1;
}
@@ -1393,32 +1399,6 @@
return 1;
}
- // Must come before ResourceFileFlattener as ResourceFileFlattener
- // relies on the minSdkVersion to properly flatten files.
- Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(),
- mContext->getDiagnostics());
- if (maybeAppInfo && maybeAppInfo.value().minSdkVersion) {
- if (Maybe<int> maybeMinSdkVersion =
- ResourceUtils::tryParseSdkVersion(maybeAppInfo.value().minSdkVersion.value())) {
- mContext->setMinSdkVersion(maybeMinSdkVersion.value());
- }
- }
-
- ResourceFileFlattenerOptions fileFlattenerOptions;
- fileFlattenerOptions.keepRawValues = mOptions.staticLib;
- fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
- fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
- fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
- fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
- fileFlattenerOptions.updateProguardSpec =
- static_cast<bool>(mOptions.generateProguardRulesPath);
- ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
-
- if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
- return 1;
- }
-
if (!mOptions.noAutoVersion) {
AutoVersioner versioner;
if (!versioner.consume(mContext, &mFinalTable)) {
@@ -1440,6 +1420,23 @@
}
}
+ // Write out the table to an archive. Optimizations to the table should come before this
+ // step.
+ ResourceFileFlattenerOptions fileFlattenerOptions;
+ fileFlattenerOptions.keepRawValues = mOptions.staticLib;
+ fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
+ fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
+ fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
+ fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
+ fileFlattenerOptions.updateProguardSpec =
+ static_cast<bool>(mOptions.generateProguardRulesPath);
+ ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
+
+ if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
+ return 1;
+ }
+
if (mOptions.staticLib) {
if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) {
mContext->getDiagnostics()->error(DiagMessage()
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 1203db7..e7edcc5 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -81,6 +81,22 @@
return true;
}
+/**
+ * The coreApp attribute in <manifest> is not a regular AAPT attribute, so type checking on it
+ * is manual.
+ */
+static bool fixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
+ if (xml::Attribute* attr = el->findAttribute("", "coreApp")) {
+ std::unique_ptr<BinaryPrimitive> result = ResourceUtils::tryParseBool(attr->value);
+ if (!result) {
+ diag->error(DiagMessage(el->lineNumber) << "attribute coreApp must be a boolean");
+ return false;
+ }
+ attr->compiledValue = std::move(result);
+ }
+ return true;
+}
+
bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) {
// First verify some options.
if (mOptions.renameManifestPackage) {
@@ -111,6 +127,7 @@
// Manifest actions.
xml::XmlNodeAction& manifestAction = (*executor)["manifest"];
manifestAction.action(verifyManifest);
+ manifestAction.action(fixCoreAppAttribute);
manifestAction.action([&](xml::Element* el) -> bool {
if (mOptions.versionNameDefault) {
if (el->findAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 1c69a8c..16ab9ab 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -253,4 +253,24 @@
EXPECT_EQ(std::string("0x10000000"), attr->value);
}
+TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
+ EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"hello\" />"));
+ EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
+
+ std::unique_ptr<xml::XmlResource> doc =
+ verify("<manifest package=\"android\" coreApp=\"true\" />");
+ ASSERT_NE(nullptr, doc);
+
+ xml::Element* el = xml::findRootElement(doc.get());
+ ASSERT_NE(nullptr, el);
+
+ EXPECT_EQ("manifest", el->name);
+
+ xml::Attribute* attr = el->findAttribute("", "coreApp");
+ ASSERT_NE(nullptr, attr);
+
+ EXPECT_NE(nullptr, attr->compiledValue);
+ EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(attr->compiledValue.get()));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 2cd2639..379c991 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -135,14 +135,14 @@
const bool manglePackage,
const bool overlay,
const bool allowNewResources,
- FileMergeCallback callback) {
+ const FileMergeCallback& callback) {
bool error = false;
for (auto& srcType : srcPackage->types) {
ResourceTableType* dstType = mMasterPackage->findOrCreateType(srcType->type);
if (srcType->symbolStatus.state == SymbolState::kPublic) {
if (dstType->symbolStatus.state == SymbolState::kPublic && dstType->id && srcType->id
- && dstType->id.value() == srcType->id.value()) {
+ && dstType->id.value() != srcType->id.value()) {
// Both types are public and have different IDs.
mContext->getDiagnostics()->error(DiagMessage(src)
<< "can not merge type '"
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 6997f93..3473a27 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -115,7 +115,7 @@
const bool manglePackage,
const bool overlay,
const bool allowNewResources,
- FileMergeCallback callback);
+ const FileMergeCallback& callback);
std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package,
const FileReference& value);
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 300b56d..ff3e21f 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -164,6 +164,63 @@
EXPECT_EQ(0x0u, foo->value.data);
}
+TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
+ std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
+ .setPackageId("", 0x7f)
+ .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+ .build();
+ std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
+ .setPackageId("", 0x7f)
+ .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+ .build();
+
+ ResourceTable finalTable;
+ TableMergerOptions tableMergerOptions;
+ tableMergerOptions.autoAddOverlay = false;
+ TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+
+ ASSERT_TRUE(merger.merge({}, base.get()));
+ ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
+}
+
+TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
+ std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
+ .setPackageId("", 0x7f)
+ .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+ .build();
+ std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
+ .setPackageId("", 0x7f)
+ .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), SymbolState::kPublic)
+ .build();
+
+ ResourceTable finalTable;
+ TableMergerOptions tableMergerOptions;
+ tableMergerOptions.autoAddOverlay = false;
+ TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+
+ ASSERT_TRUE(merger.merge({}, base.get()));
+ ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
+}
+
+TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
+ std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
+ .setPackageId("", 0x7f)
+ .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+ .build();
+ std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
+ .setPackageId("", 0x7f)
+ .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), SymbolState::kPublic)
+ .build();
+
+ ResourceTable finalTable;
+ TableMergerOptions tableMergerOptions;
+ tableMergerOptions.autoAddOverlay = false;
+ TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+
+ ASSERT_TRUE(merger.merge({}, base.get()));
+ ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
+}
+
TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
.setPackageId("", 0x7f)
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 02af5e3..a29d8dc 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -126,8 +126,9 @@
mError = true;
}
- } else {
- // We still encode references.
+ } else if (!attr.compiledValue) {
+ // We still encode references, but only if we haven't manually set this to
+ // another compiled value.
attr.compiledValue = ResourceUtils::tryParseReference(attr.value);
}
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 6c506df..0c92718 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -63,7 +63,7 @@
return nullptr;
}
-const SymbolTable::Symbol* SymbolTable::findById(ResourceId id) {
+const SymbolTable::Symbol* SymbolTable::findById(const ResourceId& id) {
if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
return s.get();
}
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 43f4dd7..bd01b64 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -86,7 +86,7 @@
* are typically stored in a cache which may evict entries.
*/
const Symbol* findByName(const ResourceName& name);
- const Symbol* findById(ResourceId id);
+ const Symbol* findById(const ResourceId& id);
/**
* Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 98ff87f..ca25c6a 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -228,7 +228,7 @@
}
} else if (pbValue.has_compound_value()) {
- const pb::CompoundValue pbCompoundValue = pbValue.compound_value();
+ const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
if (pbCompoundValue.has_attr()) {
const pb::Attribute& pbAttr = pbCompoundValue.attr();
std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 3674f0f..b62ffac 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -89,7 +89,7 @@
WifiInfo getConnectionInfo();
- boolean setWifiEnabled(boolean enable);
+ boolean setWifiEnabled(String packageName, boolean enable);
int getWifiEnabledState();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6cf1921..b134cf7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -19,6 +19,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
@@ -561,6 +562,28 @@
public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
/**
+ * Activity Action: Show UI to get user approval to enable WiFi.
+ * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
+ * the name of the app requesting the action.
+ * <p>Output: Nothing.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE";
+
+ /**
+ * Activity Action: Show UI to get user approval to disable WiFi.
+ * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
+ * the name of the app requesting the action.
+ * <p>Output: Nothing.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE";
+
+ /**
* Internally used Wi-Fi lock mode representing the case were no locks are held.
* @hide
*/
@@ -1443,7 +1466,7 @@
*/
public boolean setWifiEnabled(boolean enabled) {
try {
- return mService.setWifiEnabled(enabled);
+ return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}