Merge "Move 'un/install' to cmd"
diff --git a/api/current.txt b/api/current.txt
index 84e9079..c161242 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15511,6 +15511,7 @@
field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
+ field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
field public static final int CRYPTO_MODE_AES_CTR = 1; // 0x1
field public static final int CRYPTO_MODE_UNENCRYPTED = 0; // 0x0
field public static final deprecated int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
@@ -15562,6 +15563,7 @@
public static final class MediaCodec.CryptoInfo {
ctor public MediaCodec.CryptoInfo();
method public void set(int, int[], int[], byte[], byte[], int);
+ method public void setPattern(android.media.MediaCodec.CryptoInfo.Pattern);
field public byte[] iv;
field public byte[] key;
field public int mode;
@@ -15570,6 +15572,13 @@
field public int numSubSamples;
}
+ public static final class MediaCodec.CryptoInfo.Pattern {
+ ctor public MediaCodec.CryptoInfo.Pattern(int, int);
+ method public int getEncryptBlocks();
+ method public int getSkipBlocks();
+ method public void set(int, int);
+ }
+
public static abstract interface MediaCodec.OnFrameRenderedListener {
method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 31634bf..dd6a2839 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -16796,6 +16796,7 @@
field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
+ field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
field public static final int CRYPTO_MODE_AES_CTR = 1; // 0x1
field public static final int CRYPTO_MODE_UNENCRYPTED = 0; // 0x0
field public static final deprecated int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
@@ -16847,6 +16848,7 @@
public static final class MediaCodec.CryptoInfo {
ctor public MediaCodec.CryptoInfo();
method public void set(int, int[], int[], byte[], byte[], int);
+ method public void setPattern(android.media.MediaCodec.CryptoInfo.Pattern);
field public byte[] iv;
field public byte[] key;
field public int mode;
@@ -16855,6 +16857,13 @@
field public int numSubSamples;
}
+ public static final class MediaCodec.CryptoInfo.Pattern {
+ ctor public MediaCodec.CryptoInfo.Pattern(int, int);
+ method public int getEncryptBlocks();
+ method public int getSkipBlocks();
+ method public void set(int, int);
+ }
+
public static abstract interface MediaCodec.OnFrameRenderedListener {
method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
}
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 6f65889..7f9a5d3 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -955,7 +955,6 @@
mStarted = true;
mPaused = false;
mRunning = false;
- mAnimationEndRequested = false;
AnimationHandler animationHandler = AnimationHandler.getInstance();
animationHandler.addAnimationFrameCallback(this, (long) (mStartDelay * sDurationScale));
@@ -1123,6 +1122,8 @@
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
System.identityHashCode(this));
}
+
+ mAnimationEndRequested = false;
initAnimation();
mRunning = true;
if (mSeekFraction >= 0) {
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 477b62c..53b773a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1505,21 +1505,27 @@
*
* @hide
*/
- public static String localeToResourceQualifier(Locale loc) {
+ public static String localesToResourceQualifier(LocaleList locs) {
StringBuilder sb = new StringBuilder();
- boolean l = (loc.getLanguage().length() != 0);
- boolean c = (loc.getCountry().length() != 0);
- boolean s = (loc.getScript().length() != 0);
- boolean v = (loc.getVariant().length() != 0);
- // TODO: take script and extensions into account
- if (l) {
- sb.append(loc.getLanguage());
- if (c) {
- sb.append("-r").append(loc.getCountry());
- if (s) {
- sb.append("-s").append(loc.getScript());
- if (v) {
- sb.append("-v").append(loc.getVariant());
+ for (int i = 0; i < locs.size(); i++) {
+ Locale loc = locs.get(i);
+ boolean l = (loc.getLanguage().length() != 0);
+ boolean c = (loc.getCountry().length() != 0);
+ boolean s = (loc.getScript().length() != 0);
+ boolean v = (loc.getVariant().length() != 0);
+ // TODO: take script and extensions into account
+ if (l) {
+ if (sb.length() != 0) {
+ sb.append(",");
+ }
+ sb.append(loc.getLanguage());
+ if (c) {
+ sb.append("-r").append(loc.getCountry());
+ if (s) {
+ sb.append("-s").append(loc.getScript());
+ if (v) {
+ sb.append("-v").append(loc.getVariant());
+ }
}
}
}
@@ -1544,9 +1550,8 @@
}
}
- // TODO: send the whole locale list
- if (config.locale != null && !config.locale.getLanguage().isEmpty()) {
- parts.add(localeToResourceQualifier(config.locale));
+ if (!config.mLocaleList.isEmpty()) {
+ parts.add(localesToResourceQualifier(config.mLocaleList));
}
switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 7164747..998c72a 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -811,6 +811,65 @@
}
@SmallTest
+ public void testEndBeforeStart() throws Throwable {
+ // This test calls two animators that are not yet started. One animator has completed a
+ // previous run but hasn't started since then, the other one has never run. When end() is
+ // called on these two animators, we expected their animation listeners to receive both
+ // onAnimationStarted(Animator) and onAnimationEnded(Animator) callbacks, in that sequence.
+
+ a1.setStartDelay(20);
+
+ // First start a1's first run.
+ final MyListener normalEndingListener = new MyListener();
+ a1.addListener(normalEndingListener);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(a1.isStarted());
+ assertFalse(normalEndingListener.startCalled);
+ assertFalse(normalEndingListener.endCalled);
+ // Start normally
+ a1.start();
+ }
+ });
+
+ Thread.sleep(a1.getTotalDuration() + POLL_INTERVAL);
+
+ // a1 should have finished by now.
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Call end() on both a1 and a2 without calling start()
+ final MyListener l1 = new MyListener();
+ a1.addListener(l1);
+ final MyListener l2 = new MyListener();
+ a2.addListener(l2);
+
+ assertFalse(a1.isStarted());
+ assertFalse(l1.startCalled);
+ assertFalse(l1.endCalled);
+ assertFalse(a2.isStarted());
+ assertFalse(l2.startCalled);
+ assertFalse(l1.endCalled);
+
+ a1.end();
+ a2.end();
+
+ // Check that both animators' listeners have received the animation callbacks.
+ assertTrue(l1.startCalled);
+ assertTrue(l1.endCalled);
+ assertFalse(a1.isStarted());
+ assertTrue(l1.endTime >= l1.startTime);
+
+ assertTrue(l2.startCalled);
+ assertTrue(l2.endCalled);
+ assertFalse(a2.isStarted());
+ assertTrue(l2.endTime >= l1.startTime);
+ }
+ });
+ }
+
+ @SmallTest
public void testZeroDuration() throws Throwable {
// Run two animators with zero duration, with one running forward and the other one
// backward. Check that the animations start and finish with the correct end fractions.
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 6c224e5..478fd99 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2179,6 +2179,7 @@
// in media/hardware/CryptoAPI.h !
public static final int CRYPTO_MODE_UNENCRYPTED = 0;
public static final int CRYPTO_MODE_AES_CTR = 1;
+ public static final int CRYPTO_MODE_AES_CBC = 2;
/**
* Metadata describing the structure of a (at least partially) encrypted
@@ -2186,27 +2187,14 @@
* A buffer's data is considered to be partitioned into "subSamples",
* each subSample starts with a (potentially empty) run of plain,
* unencrypted bytes followed by a (also potentially empty) run of
- * encrypted bytes.
- * numBytesOfClearData can be null to indicate that all data is encrypted.
- * This information encapsulates per-sample metadata as outlined in
- * ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base media file format files".
+ * encrypted bytes. If pattern encryption applies, each of the latter runs
+ * is encrypted only partly, according to a repeating pattern of "encrypt"
+ * and "skip" blocks. numBytesOfClearData can be null to indicate that all
+ * data is encrypted. This information encapsulates per-sample metadata as
+ * outlined in ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base
+ * media file format files".
*/
public final static class CryptoInfo {
- public void set(
- int newNumSubSamples,
- @NonNull int[] newNumBytesOfClearData,
- @NonNull int[] newNumBytesOfEncryptedData,
- @NonNull byte[] newKey,
- @NonNull byte[] newIV,
- int newMode) {
- numSubSamples = newNumSubSamples;
- numBytesOfClearData = newNumBytesOfClearData;
- numBytesOfEncryptedData = newNumBytesOfEncryptedData;
- key = newKey;
- iv = newIV;
- mode = newMode;
- }
-
/**
* The number of subSamples that make up the buffer's contents.
*/
@@ -2220,7 +2208,7 @@
*/
public int[] numBytesOfEncryptedData;
/**
- * A 16-byte opaque key
+ * A 16-byte key id
*/
public byte[] key;
/**
@@ -2229,10 +2217,84 @@
public byte[] iv;
/**
* The type of encryption that has been applied,
- * see {@link #CRYPTO_MODE_UNENCRYPTED} and {@link #CRYPTO_MODE_AES_CTR}.
+ * see {@link #CRYPTO_MODE_UNENCRYPTED}, {@link #CRYPTO_MODE_AES_CTR}
+ * and {@link #CRYPTO_MODE_AES_CBC}
*/
public int mode;
+ /**
+ * Metadata describing encryption pattern for the protected bytes in a subsample.
+ */
+ public final static class Pattern {
+ /**
+ * Number of blocks to be encrypted in the pattern. If zero, pattern
+ * encryption is inoperative.
+ */
+ private int mEncryptBlocks;
+
+ /**
+ * Number of blocks to be skipped (left clear) in the pattern. If zero,
+ * pattern encryption is inoperative.
+ */
+ private int mSkipBlocks;
+
+ /**
+ * Construct a sample encryption pattern given the number of blocks to
+ * encrypt and skip in the pattern.
+ */
+ public Pattern(int blocksToEncrypt, int blocksToSkip) {
+ set(blocksToEncrypt, blocksToSkip);
+ }
+
+ /**
+ * Set the number of blocks to encrypt and skip in a sample encryption
+ * pattern.
+ */
+ public void set(int blocksToEncrypt, int blocksToSkip) {
+ mEncryptBlocks = blocksToEncrypt;
+ mSkipBlocks = blocksToSkip;
+ }
+
+ /**
+ * Return the number of blocks to skip in a sample encryption pattern.
+ */
+ public int getSkipBlocks() {
+ return mSkipBlocks;
+ }
+
+ /**
+ * Return the number of blocks to encrypt in a sample encryption pattern.
+ */
+ public int getEncryptBlocks() {
+ return mEncryptBlocks;
+ }
+ };
+
+ /**
+ * The pattern applicable to the protected data in each subsample.
+ */
+ private Pattern pattern;
+
+ public void set(
+ int newNumSubSamples,
+ @NonNull int[] newNumBytesOfClearData,
+ @NonNull int[] newNumBytesOfEncryptedData,
+ @NonNull byte[] newKey,
+ @NonNull byte[] newIV,
+ int newMode) {
+ numSubSamples = newNumSubSamples;
+ numBytesOfClearData = newNumBytesOfClearData;
+ numBytesOfEncryptedData = newNumBytesOfEncryptedData;
+ key = newKey;
+ iv = newIV;
+ mode = newMode;
+ pattern = new Pattern(0, 0);
+ }
+
+ public void setPattern(Pattern newPattern) {
+ pattern = newPattern;
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 9ea6722..f36d640 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -20,6 +20,7 @@
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -41,6 +42,7 @@
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Video;
import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.sax.Element;
import android.sax.ElementListener;
import android.sax.RootElement;
@@ -324,8 +326,6 @@
// used when scanning the image database so we know whether we have to prune
// old thumbnail files
private int mOriginalCount;
- /** Whether the database had any entries in it before the scan started */
- private boolean mWasEmptyPriorToScan = false;
/** Whether the scanner has set a default sound for the ringer ringtone. */
private boolean mDefaultRingtoneSet;
/** Whether the scanner has set a default sound for the notification ringtone. */
@@ -535,6 +535,18 @@
if (mMtpObjectHandle != 0) {
entry.mRowId = 0;
}
+
+ if ((!mDefaultNotificationSet &&
+ doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename))
+ || (!mDefaultRingtoneSet &&
+ doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename))
+ || (!mDefaultAlarmSet &&
+ doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename))) {
+ Log.w(TAG, "forcing rescan of " + entry.mPath +
+ "since ringtone setting didn't finish");
+ scanAlways = true;
+ }
+
// rescan for metadata if file was modified since last scan
if (entry != null && (entry.mLastModifiedChanged || scanAlways)) {
if (noMedia) {
@@ -914,6 +926,26 @@
}
Uri result = null;
boolean needToSetSettings = false;
+ // Setting a flag in order not to use bulk insert for the file related with
+ // notifications, ringtones, and alarms, because the rowId of the inserted file is
+ // needed.
+ if (notifications && !mDefaultNotificationSet) {
+ if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
+ doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
+ needToSetSettings = true;
+ }
+ } else if (ringtones && !mDefaultRingtoneSet) {
+ if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
+ doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
+ needToSetSettings = true;
+ }
+ } else if (alarms && !mDefaultAlarmSet) {
+ if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) ||
+ doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) {
+ needToSetSettings = true;
+ }
+ }
+
if (rowId == 0) {
if (mMtpObjectHandle != 0) {
values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
@@ -925,28 +957,6 @@
}
values.put(Files.FileColumns.FORMAT, format);
}
- // Setting a flag in order not to use bulk insert for the file related with
- // notifications, ringtones, and alarms, because the rowId of the inserted file is
- // needed.
- if (mWasEmptyPriorToScan) {
- if (notifications && !mDefaultNotificationSet) {
- if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
- doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
- needToSetSettings = true;
- }
- } else if (ringtones && !mDefaultRingtoneSet) {
- if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
- doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
- needToSetSettings = true;
- }
- } else if (alarms && !mDefaultAlarmSet) {
- if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) ||
- doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) {
- needToSetSettings = true;
- }
- }
- }
-
// New file, insert it.
// Directories need to be inserted before the files they contain, so they
// get priority when bulk inserting.
@@ -1016,13 +1026,20 @@
private void setSettingIfNotSet(String settingName, Uri uri, long rowId) {
+ if(wasSettingAlreadySet(settingName)) {
+ return;
+ }
+
String existingSettingValue = Settings.System.getString(mContext.getContentResolver(),
settingName);
if (TextUtils.isEmpty(existingSettingValue)) {
// Set the setting to the given URI
- Settings.System.putString(mContext.getContentResolver(), settingName,
+
+ ContentResolver cr = mContext.getContentResolver();
+ Settings.System.putString(cr, settingName,
ContentUris.withAppendedId(uri, rowId).toString());
+ Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
}
}
@@ -1050,6 +1067,20 @@
}; // end of anonymous MediaScannerClient instance
+ private String settingSetIndicatorName(String base) {
+ return base + "_set";
+ }
+
+ private boolean wasSettingAlreadySet(String name) {
+ ContentResolver cr = mContext.getContentResolver();
+ String indicatorName = settingSetIndicatorName(name);
+ try {
+ return Settings.System.getInt(cr, indicatorName) != 0;
+ } catch (SettingNotFoundException e) {
+ return false;
+ }
+ }
+
private void prescan(String filePath, boolean prescanFiles) throws RemoteException {
Cursor c = null;
String where = null;
@@ -1071,6 +1102,10 @@
selectionArgs = new String[] { "" };
}
+ mDefaultRingtoneSet = wasSettingAlreadySet(Settings.System.RINGTONE);
+ mDefaultNotificationSet = wasSettingAlreadySet(Settings.System.NOTIFICATION_SOUND);
+ mDefaultAlarmSet = wasSettingAlreadySet(Settings.System.ALARM_ALERT);
+
// Tell the provider to not delete the file.
// If the file is truly gone the delete is unnecessary, and we want to avoid
// accidentally deleting files that are really there (this may happen if the
@@ -1089,7 +1124,6 @@
// with CursorWindow positioning.
long lastId = Long.MIN_VALUE;
Uri limitUri = mFilesUri.buildUpon().appendQueryParameter("limit", "1000").build();
- mWasEmptyPriorToScan = true;
while (true) {
selectionArgs[0] = "" + lastId;
@@ -1108,7 +1142,6 @@
if (num == 0) {
break;
}
- mWasEmptyPriorToScan = false;
while (c.moveToNext()) {
long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
String path = c.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
@@ -1260,7 +1293,7 @@
}
}
- private void postscan(String[] directories) throws RemoteException {
+ private void postscan(final String[] directories) throws RemoteException {
// handle playlists last, after we know what media files are on the storage.
if (mProcessPlaylists) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 09efefa..d7664ab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3058,22 +3058,23 @@
* purposefully done before acquiring {@link #mPackages} lock.
*/
private int augmentFlagsForUser(int flags, int userId) {
- final IActivityManager am = ActivityManagerNative.getDefault();
- if (am == null) {
- // We must be early in boot, so the best we can do is assume the
- // user is fully running.
- return flags;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- if (am.isUserRunning(userId, ActivityManager.FLAG_WITH_AMNESIA)) {
- flags |= PackageManager.FLAG_USER_RUNNING_WITH_AMNESIA;
- }
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ // TODO: bring back once locking fixed
+// final IActivityManager am = ActivityManagerNative.getDefault();
+// if (am == null) {
+// // We must be early in boot, so the best we can do is assume the
+// // user is fully running.
+// return flags;
+// }
+// final long token = Binder.clearCallingIdentity();
+// try {
+// if (am.isUserRunning(userId, ActivityManager.FLAG_WITH_AMNESIA)) {
+// flags |= PackageManager.FLAG_USER_RUNNING_WITH_AMNESIA;
+// }
+// } catch (RemoteException e) {
+// throw e.rethrowAsRuntimeException();
+// } finally {
+// Binder.restoreCallingIdentity(token);
+// }
return flags;
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 68034c8..25ef8e6 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -295,6 +295,9 @@
Bitmap getAppTransitionThumbnailHeader(int taskId) {
AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+ if (spec == null) {
+ spec = mDefaultNextAppTransitionAnimationSpec;
+ }
return spec != null ? spec.bitmap : null;
}
@@ -545,6 +548,9 @@
void getNextAppTransitionStartRect(int taskId, Rect rect) {
AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+ if (spec == null) {
+ spec = mDefaultNextAppTransitionAnimationSpec;
+ }
if (spec == null || spec.rect == null) {
Slog.wtf(TAG, "Starting rect for task: " + taskId + " requested, but not available",
new Throwable());
@@ -554,9 +560,10 @@
}
}
- private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height) {
+ private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height,
+ Bitmap bitmap) {
mDefaultNextAppTransitionAnimationSpec = new AppTransitionAnimationSpec(-1 /* taskId */,
- null /* bitmap */, new Rect(left, top, left + width, top + height));
+ bitmap, new Rect(left, top, left + width, top + height));
}
private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) {
@@ -1346,7 +1353,7 @@
mNextAppTransitionPackage = null;
mNextAppTransitionAnimationsSpecs.clear();
putDefaultNextAppTransitionCoordinates(startX, startY, startX + startWidth,
- startY + startHeight);
+ startY + startHeight, null);
postAnimationCallback();
mNextAppTransitionCallback = null;
mAnimationFinishedCallback = null;
@@ -1357,7 +1364,7 @@
int startWidth, int startHeight) {
if (isTransitionSet()) {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
- putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight);
+ putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
postAnimationCallback();
mNextAppTransitionCallback = null;
mAnimationFinishedCallback = null;
@@ -1372,7 +1379,7 @@
mNextAppTransitionPackage = null;
mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
- putDefaultNextAppTransitionCoordinates(startX, startY, 0 ,0);
+ putDefaultNextAppTransitionCoordinates(startX, startY, 0, 0, srcThumb);
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
mAnimationFinishedCallback = null;
@@ -1389,7 +1396,8 @@
mNextAppTransitionPackage = null;
mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
- putDefaultNextAppTransitionCoordinates(startX, startY, targetWidth, targetHeight);
+ putDefaultNextAppTransitionCoordinates(startX, startY, targetWidth, targetHeight,
+ srcThumb);
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
mAnimationFinishedCallback = null;
@@ -1417,7 +1425,7 @@
// be set.
Rect rect = spec.rect;
putDefaultNextAppTransitionCoordinates(rect.left, rect.top, rect.width(),
- rect.height());
+ rect.height(), null);
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 87ad1f88..05e88ca 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8726,9 +8726,11 @@
// we need to go through the process of getting informed by the
// application when it has finished drawing.
if (w.mOrientationChanging || dragResizingChanged) {
- if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
- + w + ", surfaceController " + winAnimator.mSurfaceController);
+ if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
+ Slog.v(TAG, "Orientation or resize start waiting for draw"
+ + ", mDrawState=DRAW_PENDING in " + w
+ + ", surfaceController " + winAnimator.mSurfaceController);
+ }
winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
if (w.mAppToken != null) {
w.mAppToken.allDrawn = false;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 81d0b4d..10f737f 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -475,7 +475,9 @@
if (!mLastHidden) {
//dump();
mLastHidden = true;
- mSurfaceController.hideInTransaction(reason);
+ if (mSurfaceController != null) {
+ mSurfaceController.hideInTransaction(reason);
+ }
}
}
@@ -537,7 +539,9 @@
return;
}
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "SET FREEZE LAYER", null);
- mSurfaceController.setLayer(mAnimLayer + 1);
+ if (mSurfaceController != null) {
+ mSurfaceController.setLayer(mAnimLayer + 1);
+ }
mDestroyPreservedSurfaceUponRedraw = true;
mSurfaceDestroyDeferred = true;
destroySurfaceLocked();
@@ -752,7 +756,11 @@
WindowManagerService.logSurface(mWin, "DESTROY", null);
destroySurface();
}
- mWallpaperControllerLocked.hideWallpapers(mWin);
+ // Don't hide wallpaper if we're deferring the surface destroy
+ // because of a surface change.
+ if (!(mSurfaceDestroyDeferred && mDestroyPreservedSurfaceUponRedraw)) {
+ mWallpaperControllerLocked.hideWallpapers(mWin);
+ }
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window " + this
+ " surface " + mSurfaceController + " session " + mSession
@@ -783,7 +791,11 @@
WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
}
mPendingDestroySurface.destroyInTransaction();
- mWallpaperControllerLocked.hideWallpapers(mWin);
+ // Don't hide wallpaper if we're destroying a deferred surface
+ // after a surface mode change.
+ if (!mDestroyPreservedSurfaceUponRedraw) {
+ mWallpaperControllerLocked.hideWallpapers(mWin);
+ }
}
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window "
@@ -1328,6 +1340,10 @@
}
void setTransparentRegionHintLocked(final Region region) {
+ if (mSurfaceController == null) {
+ Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
+ return;
+ }
mSurfaceController.setTransparentRegionHint(region);
}
@@ -1374,10 +1390,16 @@
}
void setOpaqueLocked(boolean isOpaque) {
+ if (mSurfaceController == null) {
+ return;
+ }
mSurfaceController.setOpaque(isOpaque);
}
void setSecureLocked(boolean isSecure) {
+ if (mSurfaceController == null) {
+ return;
+ }
mSurfaceController.setSecure(isSecure);
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 92ea66b..4b9a538 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1474,6 +1474,7 @@
final int taskId = appToken.mTask.mTaskId;
Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) {
+ if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
return;
}
// This thumbnail animation is very special, we need to have
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6b1b6296..3b281e2 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4848,4 +4848,21 @@
}
return null;
}
-}
+
+ /**
+ * Returns the service state information on specified subscription. Callers require
+ * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
+ * @hide
+ */
+ public ServiceState getServiceStateForSubscriber(int subId) {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getServiceStateForSubscriber(subId, getOpPackageName());
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index dcece26..8172e94 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -21,9 +21,10 @@
import android.telecom.PhoneAccount;
import android.telephony.CellInfo;
import android.telephony.IccOpenLogicalChannelResponse;
+import android.telephony.ModemActivityInfo;
import android.telephony.NeighboringCellInfo;
import android.telephony.RadioAccessFamily;
-import android.telephony.ModemActivityInfo;
+import android.telephony.ServiceState;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.OperatorInfo;
import java.util.List;
@@ -1005,4 +1006,12 @@
* Return the modem activity info.
*/
ModemActivityInfo getModemActivityInfo();
+
+ /**
+ * Get the service state on specified subscription
+ * @param subId Subscription id
+ * @param callingPackage The package making the call
+ * @return Service state on specified subscription.
+ */
+ ServiceState getServiceStateForSubscriber(int subId, String callingPackage);
}