Merge "Remove screenshot APIs." into mnc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 3209169..afd82e3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -111,6 +111,7 @@
field public static final java.lang.String INVOKE_CARRIER_SETUP = "android.permission.INVOKE_CARRIER_SETUP";
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
field public static final java.lang.String KILL_UID = "android.permission.KILL_UID";
+ field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1e9bc54..15cfbcd 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2466,13 +2466,6 @@
return true;
}
- case SYSTEM_BACKUP_RESTORED: {
- data.enforceInterface(IActivityManager.descriptor);
- systemBackupRestored();
- reply.writeNoException();
- return true;
- }
-
case NOTIFY_CLEARTEXT_NETWORK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
final int uid = data.readInt();
@@ -5759,17 +5752,6 @@
}
@Override
- public void systemBackupRestored() throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(SYSTEM_BACKUP_RESTORED, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- @Override
public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 05a936c..4ba1055 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -488,7 +488,6 @@
public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
public void notifyEnterAnimationComplete(IBinder token) throws RemoteException;
- public void systemBackupRestored() throws RemoteException;
public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException;
public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
@@ -825,7 +824,6 @@
int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240;
int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241;
int REGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+242;
- int SYSTEM_BACKUP_RESTORED = IBinder.FIRST_CALL_TRANSACTION+243;
// Start of M transactions
int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
diff --git a/core/java/android/app/backup/RecentsBackupHelper.java b/core/java/android/app/backup/RecentsBackupHelper.java
deleted file mode 100644
index 1a64da6..0000000
--- a/core/java/android/app/backup/RecentsBackupHelper.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.backup;
-
-import android.content.Context;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.util.Slog;
-
-import java.io.File;
-
-/**
- * Helper for saving/restoring 'recent tasks' infrastructure.
- * @hide
- */
-public class RecentsBackupHelper implements BackupHelper {
- private static final String TAG = "RecentsBackup";
- private static final boolean DEBUG = false;
-
- // This must match TaskPersister.TASKS_DIRNAME, but that class is not accessible from here
- private static final String RECENTS_TASK_DIR = "recent_tasks";
-
- // Must match TaskPersister.IMAGES_DIRNAME, as above
- private static final String RECENTS_IMAGE_DIR = "recent_images";
-
- // At restore time, tasks/thumbnails are placed in these directories alongside
- // the "live" recents dirs named above.
- private static final String RECENTS_TASK_RESTORE_DIR = "restored_" + RECENTS_TASK_DIR;
- private static final String RECENTS_IMAGE_RESTORE_DIR = "restored_" + RECENTS_IMAGE_DIR;
-
- // Prefixes for tagging the two kinds of recents backup records that we might generate
- private static final String RECENTS_TASK_KEY = "task:";
- private static final String RECENTS_IMAGE_KEY = "image:";
-
- FileBackupHelperBase mTaskFileHelper;
-
- final File mSystemDir;
- final File mTasksDir;
- final File mRestoredTasksDir;
- final File mRestoredImagesDir;
- final String[] mRecentFiles;
- final String[] mRecentKeys;
-
- /**
- * @param context The agent context in which this helper instance will run
- */
- public RecentsBackupHelper(Context context) {
- mTaskFileHelper = new FileBackupHelperBase(context);
-
- mSystemDir = new File(Environment.getDataDirectory(), "system");
- mTasksDir = new File(mSystemDir, RECENTS_TASK_DIR);
- mRestoredTasksDir = new File(mSystemDir, RECENTS_TASK_RESTORE_DIR);
- mRestoredImagesDir = new File(mSystemDir, RECENTS_IMAGE_RESTORE_DIR);
-
- // Currently we back up only the recent-task descriptions, not the thumbnails
- File[] recentFiles = mTasksDir.listFiles();
- if (recentFiles != null) {
- // We explicitly proceed even if this is a zero-size array
- final int N = recentFiles.length;
- mRecentKeys = new String[N];
- mRecentFiles = new String[N];
- if (DEBUG) {
- Slog.i(TAG, "Identifying recents for backup: " + N);
- }
- for (int i = 0; i < N; i++) {
- mRecentKeys[i] = new String(RECENTS_TASK_KEY + recentFiles[i].getName());
- mRecentFiles[i] = recentFiles[i].getAbsolutePath();
- if (DEBUG) {
- Slog.i(TAG, " " + mRecentKeys[i]);
- }
- }
- } else {
- mRecentFiles = mRecentKeys = new String[0];
- }
- }
-
- /**
- * Task-file key: RECENTS_TASK_KEY + leaf filename
- * Thumbnail-file key: RECENTS_IMAGE_KEY + leaf filename
- */
- @Override
- public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
- ParcelFileDescriptor newState) {
- FileBackupHelperBase.performBackup_checked(oldState, data, newState,
- mRecentFiles, mRecentKeys);
- }
-
- @Override
- public void restoreEntity(BackupDataInputStream data) {
- final String key = data.getKey();
- File output = null;
- if (key.startsWith(RECENTS_TASK_KEY)) {
- String name = key.substring(RECENTS_TASK_KEY.length());
- output = new File(mRestoredTasksDir, name);
- mRestoredTasksDir.mkdirs();
- } else if (key.startsWith(RECENTS_IMAGE_KEY)) {
- String name = key.substring(RECENTS_IMAGE_KEY.length());
- output = new File(mRestoredImagesDir, name);
- mRestoredImagesDir.mkdirs();
- }
-
- if (output != null) {
- if (DEBUG) {
- Slog.i(TAG, "Restoring key='"
- + key + "' to " + output.getAbsolutePath());
- }
- mTaskFileHelper.writeFile(output, data);
- }
- }
-
- @Override
- public void writeNewStateDescription(ParcelFileDescriptor newState) {
- mTaskFileHelper.writeNewStateDescription(newState);
- }
-
-}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8768f40..b22b914 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -96,6 +96,14 @@
private static final boolean VDBG = false;
/**
+ * Default MAC address reported to a client that does not have the
+ * android.permission.LOCAL_MAC_ADDRESS permission.
+ *
+ * @hide
+ */
+ public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
+
+ /**
* Sentinel error value for this class. Guaranteed to not equal any other
* integer constant in this class. Provided as a convenience for functions
* that require a sentinel error value, for example:
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index f18b7ac..bd45007 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -80,18 +80,12 @@
/**
* The interpolator of the underlying Animator object. By default, we don't set the interpolator
- * on the Animator and just use its default interpolator. If the interpolator is ever set on
- * this Animator, then we use the interpolator that it was set to.
+ * on the Animator and just use its default interpolator. If the interpolator is set to a
+ * non-null value on this Animator, then we use the interpolator that it was set to.
*/
private TimeInterpolator mInterpolator;
/**
- * A flag indicating whether the interpolator has been set on this object. If not, we don't set
- * the interpolator on the underlying Animator, but instead just use its default interpolator.
- */
- private boolean mInterpolatorSet = false;
-
- /**
* Listener for the lifecycle events of the underlying ValueAnimator object.
*/
private Animator.AnimatorListener mListener = null;
@@ -338,7 +332,6 @@
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
- mInterpolatorSet = true;
mInterpolator = interpolator;
return this;
}
@@ -349,7 +342,7 @@
* @return The timing interpolator for this animation.
*/
public TimeInterpolator getInterpolator() {
- if (mInterpolatorSet) {
+ if (mInterpolator != null) {
return mInterpolator;
} else {
// Just return the default from ValueAnimator, since that's what we'd get if
@@ -897,7 +890,7 @@
if (mDurationSet) {
animator.setDuration(mDuration);
}
- if (mInterpolatorSet) {
+ if (mInterpolator != null) {
animator.setInterpolator(mInterpolator);
}
animator.start();
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index a80abce5..f485460 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -16,14 +16,12 @@
package com.android.server.backup;
-import android.app.ActivityManagerNative;
import android.app.IWallpaperManager;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupAgentHelper;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
-import android.app.backup.RecentsBackupHelper;
import android.app.backup.WallpaperBackupHelper;
import android.content.Context;
import android.os.Environment;
@@ -45,7 +43,6 @@
// Names of the helper tags within the dataset. Changing one of these names will
// break the ability to restore from datasets that predate the change.
private static final String WALLPAPER_HELPER = "wallpaper";
- private static final String RECENTS_HELPER = "recents";
private static final String SYNC_SETTINGS_HELPER = "account_sync_settings";
private static final String PREFERRED_HELPER = "preferred_activities";
private static final String NOTIFICATION_HELPER = "notifications";
@@ -92,7 +89,6 @@
}
}
addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, files, keys));
- addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -127,7 +123,6 @@
addHelper("system_files", new WallpaperBackupHelper(this,
new String[] { WALLPAPER_IMAGE },
new String[] { WALLPAPER_IMAGE_KEY} ));
- addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -200,13 +195,4 @@
}
}
}
-
- @Override
- public void onRestoreFinished() {
- try {
- ActivityManagerNative.getDefault().systemBackupRestored();
- } catch (RemoteException e) {
- // Not possible since this code is running in the system process.
- }
- }
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 608d718..595f9f0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -898,7 +898,9 @@
android:label="@string/permlab_changeWimaxState"
android:protectionLevel="dangerous" />
- <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+ <!--@SystemApi Allows applications to the the local WiFi and Bluetooth MAC address.
+ @hide
+ -->
<permission android:name="android.permission.SCORE_NETWORKS"
android:protectionLevel="signature|system" />
@@ -2447,6 +2449,10 @@
<permission android:name="android.permission.KILL_UID"
android:protectionLevel="signature" />
+ <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+ <permission android:name="android.permission.LOCAL_MAC_ADDRESS"
+ android:protectionLevel="signature" />
+
<!-- The system process is explicitly the only one allowed to launch the
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd
index 2801c18..3b5fdbd 100644
--- a/docs/html/preview/index.jd
+++ b/docs/html/preview/index.jd
@@ -22,21 +22,9 @@
Test your apps and give us feedback!
</p>
- <a class="dac-hero-cta" href="{@docRoot}preview/overview.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- Preview Program Overview
- </a><br>
- <a class="dac-hero-cta" href="{@docRoot}preview/api-overview.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- Review the API changes
- </a><br>
<a class="dac-hero-cta" href="{@docRoot}preview/setup-sdk.html">
<span class="dac-sprite dac-auto-chevron"></span>
- Set up the Preview SDK
- </a><br>
- <a class="dac-hero-cta" href="https://code.google.com/p/android-developer-preview/">
- <span class="dac-sprite dac-auto-chevron"></span>
- Report issues
+ Get started
</a><br>
</div>
@@ -55,6 +43,7 @@
<i class="dac-sprite dac-arrow-down-gray"></i>
</a>
</div>
+
<section class="dac-section dac-gray dac-small dac-invert" id="latest"><div class="wrap">
<h2 class="norule">Latest</h2>
<div class="resource-widget resource-flow-layout col-16"
@@ -62,22 +51,3 @@
data-cardSizes="6x6"
data-maxResults="3"></div>
</div></section>
-
-<section class="dac-section dac-light"><div class="wrap">
- <h1 class="dac-section-title">Android Data Binding</h1>
- <div class="dac-section-subtitle">
- A new way to manage your app's UI.
- </div>
-
- <ul class="dac-section-links">
- <li class="dac-section-link"><a href="">
- <span class="dac-sprite dac-auto-chevron"></span>
- Overview and Usage
- </a></li>
- <li class="dac-section-link"><a href="/google/play/filters.html">
- <span class="dac-sprite dac-auto-chevron"></span>
- User Guide
- </a></li>
-
- </ul>
-</div></section>
\ No newline at end of file
diff --git a/docs/html/tools/devices/index.jd b/docs/html/tools/devices/index.jd
index 1ea4c47..6263c8b 100644
--- a/docs/html/tools/devices/index.jd
+++ b/docs/html/tools/devices/index.jd
@@ -5,16 +5,16 @@
<p>An Android Virtual Device (AVD) is an emulator configuration that lets you model an actual
device by defining hardware and software options to be emulated by the Android Emulator.</p>
- <p>The easiest way to create an AVD is to use the graphical <a href=
- "{@docRoot}tools/devices/managing-avds.html">AVD Manager</a>, which you launch
- from Eclipse by clicking <strong>Window > AVD Manager</strong>. You can also start the AVD
-Manager from the command line by calling the <code>android</code> tool with the <code>avd</code>
-options, from the <strong><sdk>/tools/</strong> directory.</p>
+ <p>The easiest way to create an AVD is to use the graphical
+ <a href="{@docRoot}tools/devices/managing-avds.html">AVD Manager</a>, which you launch
+ from Android Studio by clicking <strong>Tools > Android > AVD Manager</strong>. You can
+ also start the AVD Manager from the command line by calling the <code>android</code> tool with
+ the <code>avd</code> options, from the <strong><sdk>/tools/</strong> directory.</p>
<p>You can also create AVDs on the command line by passing the <code>android</code> tool options.
- For more information on how to create AVDs in this manner, see <a href=
- "{@docRoot}tools/devices/managing-avds-cmdline.html">Managing Virtual
- Devices from the Command Line</a>.</p>
+ For more information on how to create AVDs in this manner, see
+ <a href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing Virtual Devices from the
+ Command Line</a>.</p>
<p>An AVD consists of:</p>
diff --git a/docs/html/tools/devices/managing-avds-cmdline.jd b/docs/html/tools/devices/managing-avds-cmdline.jd
index ba353c1..c16b1f8 100644
--- a/docs/html/tools/devices/managing-avds-cmdline.jd
+++ b/docs/html/tools/devices/managing-avds-cmdline.jd
@@ -84,8 +84,8 @@
<h2 id="AVDCmdLine">Creating AVDs</h2>
-<p>In addition to creating AVDs with the
-<a href="{@docRoot}tools/devices/managing-avds-cmdline.html">AVD Manager user interface</a>,
+<p>In addition to creating AVDs with the
+<a href="{@docRoot}tools/help/avd-manager.html">AVD Manager user interface</a>,
you can also create them by passing in command line arguments to the <code>android</code> tool.
</p>
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index ea60040..28c26ff 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -19,7 +19,6 @@
import android.animation.AnimatorSet;
import android.animation.Animator.AnimatorListener;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -128,19 +127,13 @@
* @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation
*/
public class AnimatedVectorDrawable extends Drawable implements Animatable {
- private static final String LOGTAG = "AnimatedVectorDrawable";
+ private static final String LOGTAG = AnimatedVectorDrawable.class.getSimpleName();
private static final String ANIMATED_VECTOR = "animated-vector";
private static final String TARGET = "target";
private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
- /**
- * The resources against which this drawable was created. Used to attempt
- * to inflate animators if applyTheme() doesn't get called.
- */
- private Resources mRes;
-
private AnimatedVectorDrawableState mAnimatedVectorState;
private boolean mMutated;
@@ -151,7 +144,6 @@
private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) {
mAnimatedVectorState = new AnimatedVectorDrawableState(state, mCallback, res);
- mRes = res;
}
@Override
@@ -281,7 +273,6 @@
@Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final AnimatedVectorDrawableState state = mAnimatedVectorState;
int eventType = parser.getEventType();
float pathErrorScale = 1;
@@ -299,10 +290,10 @@
vectorDrawable.setAllowCaching(false);
vectorDrawable.setCallback(mCallback);
pathErrorScale = vectorDrawable.getPixelSize();
- if (state.mVectorDrawable != null) {
- state.mVectorDrawable.setCallback(null);
+ if (mAnimatedVectorState.mVectorDrawable != null) {
+ mAnimatedVectorState.mVectorDrawable.setCallback(null);
}
- state.mVectorDrawable = vectorDrawable;
+ mAnimatedVectorState.mVectorDrawable = vectorDrawable;
}
a.recycle();
} else if (TARGET.equals(tagName)) {
@@ -311,25 +302,12 @@
final String target = a.getString(
R.styleable.AnimatedVectorDrawableTarget_name);
- final int animResId = a.getResourceId(
+ int id = a.getResourceId(
R.styleable.AnimatedVectorDrawableTarget_animation, 0);
- if (animResId != 0) {
- if (theme != null) {
- final Animator objectAnimator = AnimatorInflater.loadAnimator(
- res, theme, animResId, pathErrorScale);
- setupAnimatorsForTarget(target, objectAnimator);
- } else {
- // The animation may be theme-dependent. As a
- // workaround until Animator has full support for
- // applyTheme(), postpone loading the animator
- // until we have a theme in applyTheme().
- if (state.mPendingAnims == null) {
- state.mPendingAnims = new ArrayList<>(1);
- }
- state.mPendingAnims.add(
- new PendingAnimator(animResId, pathErrorScale, target));
-
- }
+ if (id != 0) {
+ Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id,
+ pathErrorScale);
+ setupAnimatorsForTarget(target, objectAnimator);
}
a.recycle();
}
@@ -337,13 +315,6 @@
eventType = parser.next();
}
-
- // If we don't have any pending animations, we don't need to hold a
- // reference to the resources.
- if (state.mPendingAnims == null) {
- mRes = null;
- }
-
setupAnimatorSet();
}
@@ -369,29 +340,6 @@
if (vectorDrawable != null && vectorDrawable.canApplyTheme()) {
vectorDrawable.applyTheme(t);
}
-
- if (t != null) {
- inflatePendingAnimators(t.getResources(), t);
- }
- }
-
- /**
- * Inflates pending animators, if any, against a theme. Clears the list of
- * pending animators.
- *
- * @param t the theme against which to inflate the animators
- */
- private void inflatePendingAnimators(@NonNull Resources res, @Nullable Theme t) {
- final ArrayList<PendingAnimator> pendingAnims = mAnimatedVectorState.mPendingAnims;
- if (pendingAnims != null) {
- mAnimatedVectorState.mPendingAnims = null;
-
- for (int i = 0, count = pendingAnims.size(); i < count; i++) {
- final PendingAnimator pendingAnimator = pendingAnims.get(i);
- final Animator objectAnimator = pendingAnimator.newInstance(res, t);
- setupAnimatorsForTarget(pendingAnimator.target, objectAnimator);
- }
- }
}
/**
@@ -433,7 +381,6 @@
// we add this array into the mAnimatorSet.
private ArrayList<Animator> mTempAnimators;
ArrayMap<Animator, String> mTargetNameMap;
- ArrayList<PendingAnimator> mPendingAnims;
public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy,
Callback owner, Resources res) {
@@ -456,7 +403,7 @@
final int numAnimators = copy.mTargetNameMap.size();
// Deep copy a animator set, and then setup the target map again.
mAnimatorSet = copy.mAnimatorSet.clone();
- mTargetNameMap = new ArrayMap<>(numAnimators);
+ mTargetNameMap = new ArrayMap<Animator, String>(numAnimators);
// Since the new AnimatorSet is cloned from the old one, the order must be the
// same inside the array.
ArrayList<Animator> oldAnim = copy.mAnimatorSet.getChildAnimations();
@@ -471,9 +418,6 @@
mTargetNameMap.put(newAnim.get(i), targetName);
}
}
-
- // Shallow copy since the array is immutable after inflate().
- mPendingAnims = copy.mPendingAnims;
} else {
mVectorDrawable = new VectorDrawable();
}
@@ -482,7 +426,7 @@
@Override
public boolean canApplyTheme() {
return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
- || mPendingAnims != null || super.canApplyTheme();
+ || super.canApplyTheme();
}
@Override
@@ -501,32 +445,12 @@
}
}
- /**
- * Basically a constant state for Animators until we actually implement
- * constant states for Animators.
- */
- private static class PendingAnimator {
- public final int animResId;
- public final float pathErrorScale;
- public final String target;
-
- public PendingAnimator(int animResId, float pathErrorScale, String target) {
- this.animResId = animResId;
- this.pathErrorScale = pathErrorScale;
- this.target = target;
- }
-
- public Animator newInstance(Resources res, Theme theme) {
- return AnimatorInflater.loadAnimator(res, theme, animResId, pathErrorScale);
- }
- }
-
private void setupAnimatorsForTarget(String name, Animator animator) {
Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
animator.setTarget(target);
if (mAnimatedVectorState.mTempAnimators == null) {
- mAnimatedVectorState.mTempAnimators = new ArrayList<>();
- mAnimatedVectorState.mTargetNameMap = new ArrayMap<>();
+ mAnimatedVectorState.mTempAnimators = new ArrayList<Animator>();
+ mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>();
}
mAnimatedVectorState.mTempAnimators.add(animator);
mAnimatedVectorState.mTargetNameMap.put(animator, name);
@@ -550,23 +474,6 @@
if (isStarted()) {
return;
}
-
- // Check for uninflated animators. We can remove this after we add
- // support for Animator.applyTheme(). See comments in inflate().
- if (mAnimatedVectorState.mPendingAnims != null) {
- // Attempt to load animators without applying a theme.
- if (mRes != null) {
- inflatePendingAnimators(mRes, null);
- mRes = null;
- } else {
- Log.e(LOGTAG, "Failed to load animators. Either the AnimatedVectorDrawable must be"
- + " created using a Resources object or applyTheme() must be called with"
- + " a non-null Theme object.");
- }
-
- mAnimatedVectorState.mPendingAnims = null;
- }
-
mAnimatedVectorState.mAnimatorSet.start();
invalidateSelf();
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 161a7ba7..d21762b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -192,13 +192,20 @@
/**
* The write mode indicating the write operation will block until all data has been written,
- * to be used in {@link #write(ByteBuffer, int, int)}
+ * to be used as the actual value of the writeMode parameter in
+ * {@link #write(byte[], int, int, int)}, {@link #write(short[], int, int, int)},
+ * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and
+ * {@link #write(ByteBuffer, int, int, long)}.
*/
public final static int WRITE_BLOCKING = 0;
+
/**
* The write mode indicating the write operation will return immediately after
- * queuing as much audio data for playback as possible without blocking, to be used in
- * {@link #write(ByteBuffer, int, int)}.
+ * queuing as much audio data for playback as possible without blocking,
+ * to be used as the actual value of the writeMode parameter in
+ * {@link #write(ByteBuffer, int, int)}, {@link #write(short[], int, int, int)},
+ * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and
+ * {@link #write(ByteBuffer, int, int, long)}.
*/
public final static int WRITE_NON_BLOCKING = 1;
@@ -1458,14 +1465,27 @@
//--------------------
/**
* Starts playing an AudioTrack.
+ * <p>
* If track's creation mode is {@link #MODE_STATIC}, you must have called one of
- * the {@link #write(byte[], int, int)}, {@link #write(short[], int, int)},
- * or {@link #write(float[], int, int, int)} methods.
- * If the mode is {@link #MODE_STREAM}, you can optionally prime the
- * output buffer by writing up to bufferSizeInBytes (from constructor) before starting.
- * This priming will avoid an immediate underrun, but is not required.
+ * the write methods ({@link #write(byte[], int, int)}, {@link #write(byte[], int, int, int)},
+ * {@link #write(short[], int, int)}, {@link #write(short[], int, int, int)},
+ * {@link #write(float[], int, int, int)}, or {@link #write(ByteBuffer, int, int)}) prior to
+ * play().
+ * <p>
+ * If the mode is {@link #MODE_STREAM}, you can optionally prime the data path prior to
+ * calling play(), by writing up to <code>bufferSizeInBytes</code> (from constructor).
+ * If you don’t call write() first, or if you call write() but with an insufficient amount of
+ * data, then the track will be in underrun state at play(). In this case,
+ * playback will not actually start playing until the data path is filled to a
+ * device-specific minimum level. This requirement for the path to be filled
+ * to a minimum level is also true when resuming audio playback after calling stop().
+ * Similarly the buffer will need to be filled up again after
+ * the track underruns due to failure to call write() in a timely manner with sufficient data.
+ * For portability, an application should prime the data path to the maximum allowed
+ * by writing data until the write() method returns a short transfer count.
+ * This allows play() to start immediately, and reduces the chance of underrun.
*
- * @throws IllegalStateException
+ * @throws IllegalStateException if the track isn't properly initialized
*/
public void play()
throws IllegalStateException {
@@ -1570,21 +1590,30 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
- * In streaming mode, will block until all data has been written to the audio sink.
+ * <p>
+ * In streaming mode, the write will normally block until all the data has been enqueued for
+ * playback, and will return a full transfer count. However, if the track is stopped or paused
+ * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error
+ * occurs during the write, then the write may return a short transfer count.
+ * <p>
* In static buffer mode, copies the data to the buffer starting at offset 0.
- * Note that the actual playback of this data might occur after this function
- * returns. This function is thread safe with respect to {@link #stop} calls,
- * in which case all of the specified data might not be written to the audio sink.
+ * Note that the actual playback of this data might occur after this function returns.
*
* @param audioData the array that holds the data to play.
* @param offsetInBytes the offset expressed in bytes in audioData where the data to play
* starts.
* @param sizeInBytes the number of bytes to read in audioData after the offset.
- * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * @return zero or the positive number of bytes that were written, or
+ * {@link #ERROR_INVALID_OPERATION}
+ * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
+ *
+ * This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code>
+ * set to {@link #WRITE_BLOCKING}.
*/
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING);
@@ -1595,11 +1624,17 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
- * In streaming mode, will block until all data has been written to the audio sink.
- * In static buffer mode, copies the data to the buffer starting at offset 0.
- * Note that the actual playback of this data might occur after this function
- * returns. This function is thread safe with respect to {@link #stop} calls,
- * in which case all of the specified data might not be written to the audio sink.
+ * <p>
+ * In streaming mode, the blocking behavior depends on the write mode. If the write mode is
+ * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+ * for playback, and will return a full transfer count. However, if the write mode is
+ * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+ * interrupts the write by calling stop or pause, or an I/O error
+ * occurs during the write, then the write may return a short transfer count.
+ * <p>
+ * In static buffer mode, copies the data to the buffer starting at offset 0,
+ * and the write mode is ignored.
+ * Note that the actual playback of this data might occur after this function returns.
*
* @param audioData the array that holds the data to play.
* @param offsetInBytes the offset expressed in bytes in audioData where the data to play
@@ -1611,11 +1646,14 @@
* to the audio sink.
* <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * @return zero or the positive number of bytes that were written, or
+ * {@link #ERROR_INVALID_OPERATION}
+ * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
*/
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@WriteMode int writeMode) {
@@ -1653,21 +1691,30 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
- * In streaming mode, will block until all data has been written to the audio sink.
+ * <p>
+ * In streaming mode, the write will normally block until all the data has been enqueued for
+ * playback, and will return a full transfer count. However, if the track is stopped or paused
+ * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error
+ * occurs during the write, then the write may return a short transfer count.
+ * <p>
* In static buffer mode, copies the data to the buffer starting at offset 0.
- * Note that the actual playback of this data might occur after this function
- * returns. This function is thread safe with respect to {@link #stop} calls,
- * in which case all of the specified data might not be written to the audio sink.
+ * Note that the actual playback of this data might occur after this function returns.
*
* @param audioData the array that holds the data to play.
* @param offsetInShorts the offset expressed in shorts in audioData where the data to play
* starts.
* @param sizeInShorts the number of shorts to read in audioData after the offset.
- * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * @return zero or the positive number of shorts that were written, or
+ * {@link #ERROR_INVALID_OPERATION}
+ * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
+ *
+ * This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code>
+ * set to {@link #WRITE_BLOCKING}.
*/
public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING);
@@ -1678,11 +1725,16 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
- * In streaming mode, will block until all data has been written to the audio sink.
+ * <p>
+ * In streaming mode, the blocking behavior depends on the write mode. If the write mode is
+ * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+ * for playback, and will return a full transfer count. However, if the write mode is
+ * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+ * interrupts the write by calling stop or pause, or an I/O error
+ * occurs during the write, then the write may return a short transfer count.
+ * <p>
* In static buffer mode, copies the data to the buffer starting at offset 0.
- * Note that the actual playback of this data might occur after this function
- * returns. This function is thread safe with respect to {@link #stop} calls,
- * in which case all of the specified data might not be written to the audio sink.
+ * Note that the actual playback of this data might occur after this function returns.
*
* @param audioData the array that holds the data to play.
* @param offsetInShorts the offset expressed in shorts in audioData where the data to play
@@ -1694,11 +1746,14 @@
* to the audio sink.
* <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * @return zero or the positive number of shorts that were written, or
+ * {@link #ERROR_INVALID_OPERATION}
+ * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
*/
public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@WriteMode int writeMode) {
@@ -1736,14 +1791,18 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array.
+ * <p>
+ * In streaming mode, the blocking behavior depends on the write mode. If the write mode is
+ * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+ * for playback, and will return a full transfer count. However, if the write mode is
+ * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+ * interrupts the write by calling stop or pause, or an I/O error
+ * occurs during the write, then the write may return a short transfer count.
+ * <p>
* In static buffer mode, copies the data to the buffer starting at offset 0,
* and the write mode is ignored.
- * In streaming mode, the blocking behavior will depend on the write mode.
- * <p>
- * Note that the actual playback of this data might occur after this function
- * returns. This function is thread safe with respect to {@link #stop} calls,
- * in which case all of the specified data might not be written to the audio sink.
- * <p>
+ * Note that the actual playback of this data might occur after this function returns.
+ *
* @param audioData the array that holds the data to play.
* The implementation does not clip for sample values within the nominal range
* [-1.0f, 1.0f], provided that all gains in the audio pipeline are
@@ -1763,11 +1822,14 @@
* to the audio sink.
* <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * @return zero or the positive number of floats that were written, or
+ * {@link #ERROR_INVALID_OPERATION}
+ * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
*/
public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@WriteMode int writeMode) {
@@ -1811,9 +1873,19 @@
/**
* Writes the audio data to the audio sink for playback (streaming mode),
* or copies audio data for later playback (static buffer mode).
- * In static buffer mode, copies the data to the buffer starting at its 0 offset, and the write
- * mode is ignored.
- * In streaming mode, the blocking behavior will depend on the write mode.
+ * The audioData in ByteBuffer should match the format specified in the AudioTrack constructor.
+ * <p>
+ * In streaming mode, the blocking behavior depends on the write mode. If the write mode is
+ * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+ * for playback, and will return a full transfer count. However, if the write mode is
+ * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+ * interrupts the write by calling stop or pause, or an I/O error
+ * occurs during the write, then the write may return a short transfer count.
+ * <p>
+ * In static buffer mode, copies the data to the buffer starting at offset 0,
+ * and the write mode is ignored.
+ * Note that the actual playback of this data might occur after this function returns.
+ *
* @param audioData the buffer that holds the data to play, starting at the position reported
* by <code>audioData.position()</code>.
* <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
@@ -1827,10 +1899,12 @@
* to the audio sink.
* <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return 0 or a positive number of bytes that were written, or
+ * @return zero or the positive number of bytes that were written, or
* {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
*/
public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
@WriteMode int writeMode) {
@@ -1877,8 +1951,8 @@
}
/**
- * Writes the audio data to the audio sink for playback (streaming mode) on a HW_AV_SYNC track.
- * In streaming mode, the blocking behavior will depend on the write mode.
+ * Writes the audio data to the audio sink for playback in streaming mode on a HW_AV_SYNC track.
+ * The blocking behavior will depend on the write mode.
* @param audioData the buffer that holds the data to play, starting at the position reported
* by <code>audioData.position()</code>.
* <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
@@ -1892,10 +1966,12 @@
* <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
* @param timestamp The timestamp of the first decodable audio frame in the provided audioData.
- * @return 0 or a positive number of bytes that were written, or
+ * @return zero or a positive number of bytes that were written, or
* {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
+ * The dead object error code is not returned if some data was successfully transferred.
+ * In this case, the error is returned at the next write().
*/
public int write(ByteBuffer audioData, int sizeInBytes,
@WriteMode int writeMode, long timestamp) {
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 1cabcdfc..e03f449 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
+import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -42,7 +43,7 @@
.setPackage("com.android.phone")
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@@ -127,6 +128,7 @@
KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(
true /* bypassHandler */);
getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
+ ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 17e2cb5..3feec9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -59,6 +59,12 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int ownMaxHeight = mMaxViewHeight;
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
+ if (hasFixedHeight) {
+ // We have a height set in our layout, so we want to be at most as big as given
+ ownMaxHeight = Math.min(MeasureSpec.getSize(heightMeasureSpec), ownMaxHeight);
+ }
int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
int maxChildHeight = 0;
int childCount = getChildCount();
@@ -85,7 +91,7 @@
mMatchParentViews.add(child);
}
}
- int ownHeight = Math.min(ownMaxHeight, maxChildHeight);
+ int ownHeight = hasFixedHeight ? ownMaxHeight : Math.min(ownMaxHeight, maxChildHeight);
newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
for (View child : mMatchParentViews) {
child.measure(getChildMeasureSpec(
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f5d27f9..c46fa76 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.Manifest;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
@@ -909,16 +910,22 @@
mCallbacks.finishBroadcast();
}
}
+
public String getAddress() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
- "Need BLUETOOTH permission");
+ "Need BLUETOOTH permission");
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
- (!checkIfCallerIsForegroundUser())) {
+ (!checkIfCallerIsForegroundUser())) {
Log.w(TAG,"getAddress(): not allowed for non-active and non system user");
return null;
}
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
+ != PackageManager.PERMISSION_GRANTED) {
+ return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
+ }
+
synchronized(mConnection) {
if (mBluetooth != null) {
try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a8ab667..2d74618 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6164,17 +6164,6 @@
}
}
- @Override
- public void systemBackupRestored() {
- synchronized (this) {
- if (mSystemReady) {
- mTaskPersister.restoreTasksFromOtherDeviceLocked();
- } else {
- Slog.w(TAG, "System backup restored before system is ready");
- }
- }
- }
-
final void ensureBootCompleted() {
boolean booting;
boolean enableScreen;
@@ -11327,7 +11316,6 @@
mRecentTasks.clear();
mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
- mTaskPersister.restoreTasksFromOtherDeviceLocked();
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
mTaskPersister.startPersisting();
@@ -16191,18 +16179,12 @@
removeUriPermissionsForPackageLocked(ssp, userId, true);
removeTasksByPackageNameLocked(ssp, userId);
- if (userId == UserHandle.USER_OWNER) {
- mTaskPersister.removeFromPackageCache(ssp);
- }
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
cleanupDisabledPackageComponentsLocked(ssp, userId,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
- if (userId == UserHandle.USER_OWNER) {
- mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
- }
}
}
break;
@@ -16217,9 +16199,6 @@
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
- if (userId == UserHandle.USER_OWNER) {
- mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
- }
try {
ApplicationInfo ai = AppGlobals.getPackageManager().
getApplicationInfo(ssp, 0, 0);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index f3b18f5..ca1fd6a 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,8 +17,6 @@
package com.android.server.am;
import static com.android.server.am.ActivityManagerDebugConfig.*;
-import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
-import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import android.app.ActivityManager.TaskDescription;
@@ -85,7 +83,7 @@
private static final String ATTR_USERID = "user_id";
private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
- static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
+ private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
private static final String ATTR_RESOLVEDTYPE = "resolved_type";
private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
@@ -94,7 +92,7 @@
final IApplicationToken.Stub appToken; // window manager token
final ActivityInfo info; // all about me
final ApplicationInfo appInfo; // information about activity's app
- int launchedFromUid; // always the uid who started the activity.
+ final int launchedFromUid; // always the uid who started the activity.
final String launchedFromPackage; // always the package who started the activity.
final int userId; // Which user is this running for?
final Intent intent; // the original intent that generated us
@@ -1178,8 +1176,8 @@
}
}
- static ActivityRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
- throws IOException, XmlPullParserException {
+ static ActivityRecord restoreFromXml(XmlPullParser in,
+ ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
Intent intent = null;
PersistableBundle persistentState = null;
int launchedFromUid = 0;
@@ -1194,7 +1192,7 @@
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
final String attrName = in.getAttributeName(attrNdx);
final String attrValue = in.getAttributeValue(attrNdx);
- if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
+ if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
"ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
if (ATTR_ID.equals(attrName)) {
createTime = Long.valueOf(attrValue);
@@ -1220,15 +1218,15 @@
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
- if (DEBUG_PERSISTER || DEBUG_RESTORER)
+ if (TaskPersister.DEBUG)
Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
if (TAG_INTENT.equals(name)) {
intent = Intent.restoreFromXml(in);
- if (DEBUG_PERSISTER || DEBUG_RESTORER)
+ if (TaskPersister.DEBUG)
Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
} else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
persistentState = PersistableBundle.restoreFromXml(in);
- if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
+ if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
"ActivityRecord: persistentState=" + persistentState);
} else {
Slog.w(TAG, "restoreActivity: unexpected name=" + name);
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 318cd45..ef1559a 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -59,8 +59,7 @@
public class TaskPersister {
static final String TAG = "TaskPersister";
- static final boolean DEBUG_PERSISTER = false;
- static final boolean DEBUG_RESTORER = false;
+ static final boolean DEBUG = false;
/** When not flushing don't write out files faster than this */
private static final long INTER_WRITE_DELAY_MS = 500;
@@ -81,21 +80,10 @@
private static final String IMAGES_DIRNAME = "recent_images";
static final String IMAGE_EXTENSION = ".png";
- // Directory where restored historical task XML/PNG files are placed. This directory
- // contains subdirs named after TASKS_DIRNAME and IMAGES_DIRNAME mirroring the
- // ancestral device's dataset. This needs to match the RECENTS_TASK_RESTORE_DIR
- // value in RecentsBackupHelper.
- private static final String RESTORED_TASKS_DIRNAME = "restored_" + TASKS_DIRNAME;
-
- // Max time to wait for the application/package of a restored task to be installed
- // before giving up.
- private static final long MAX_INSTALL_WAIT_TIME = DateUtils.DAY_IN_MILLIS;
-
private static final String TAG_TASK = "task";
static File sImagesDir;
static File sTasksDir;
- static File sRestoredTasksDir;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
@@ -129,23 +117,11 @@
ArrayList<WriteQueueItem> mWriteQueue = new ArrayList<WriteQueueItem>();
- // Map of tasks that were backed-up on a different device that can be restored on this device.
- // Data organization: <packageNameOfAffiliateTask, listOfAffiliatedTasksChains>
- private ArrayMap<String, List<List<OtherDeviceTask>>> mOtherDeviceTasksMap =
- new ArrayMap<>(10);
- // Local cache of package names to uid used when restoring a task from another device.
- private ArrayMap<String, Integer> mPackageUidMap;
-
- // The next time in milliseconds we will remove expired task from
- // {@link #mOtherDeviceTasksMap} and disk. Set to {@link Long.MAX_VALUE} to never clean-up
- // tasks.
- private long mExpiredTasksCleanupTime = Long.MAX_VALUE;
-
TaskPersister(File systemDir, ActivityStackSupervisor stackSupervisor,
RecentTasks recentTasks) {
sTasksDir = new File(systemDir, TASKS_DIRNAME);
if (!sTasksDir.exists()) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "Creating tasks directory " + sTasksDir);
+ if (DEBUG) Slog.d(TAG, "Creating tasks directory " + sTasksDir);
if (!sTasksDir.mkdir()) {
Slog.e(TAG, "Failure creating tasks directory " + sTasksDir);
}
@@ -153,14 +129,12 @@
sImagesDir = new File(systemDir, IMAGES_DIRNAME);
if (!sImagesDir.exists()) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "Creating images directory " + sTasksDir);
+ if (DEBUG) Slog.d(TAG, "Creating images directory " + sTasksDir);
if (!sImagesDir.mkdir()) {
Slog.e(TAG, "Failure creating images directory " + sImagesDir);
}
}
- sRestoredTasksDir = new File(systemDir, RESTORED_TASKS_DIRNAME);
-
mStackSupervisor = stackSupervisor;
mService = stackSupervisor.mService;
mRecentTasks = recentTasks;
@@ -179,8 +153,8 @@
final WriteQueueItem item = mWriteQueue.get(queueNdx);
if (item instanceof ImageWriteQueueItem &&
((ImageWriteQueueItem) item).mFilename.startsWith(taskString)) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "Removing "
- + ((ImageWriteQueueItem) item).mFilename + " from write queue");
+ if (DEBUG) Slog.d(TAG, "Removing " + ((ImageWriteQueueItem) item).mFilename +
+ " from write queue");
mWriteQueue.remove(queueNdx);
}
}
@@ -225,9 +199,9 @@
} else if (mNextWriteTime == 0) {
mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
}
- if (DEBUG_PERSISTER) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush
- + " mNextWriteTime=" + mNextWriteTime + " mWriteQueue.size="
- + mWriteQueue.size() + " Callers=" + Debug.getCallers(4));
+ if (DEBUG) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush + " mNextWriteTime="
+ + mNextWriteTime + " mWriteQueue.size=" + mWriteQueue.size()
+ + " Callers=" + Debug.getCallers(4));
notifyAll();
}
@@ -269,7 +243,7 @@
} else if (mNextWriteTime == 0) {
mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
}
- if (DEBUG_PERSISTER) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
+ if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
SystemClock.uptimeMillis() + " mNextWriteTime=" +
mNextWriteTime + " Callers=" + Debug.getCallers(4));
notifyAll();
@@ -303,12 +277,12 @@
}
private StringWriter saveToXml(TaskRecord task) throws IOException, XmlPullParserException {
- if (DEBUG_PERSISTER) Slog.d(TAG, "saveToXml: task=" + task);
+ if (DEBUG) Slog.d(TAG, "saveToXml: task=" + task);
final XmlSerializer xmlSerializer = new FastXmlSerializer();
StringWriter stringWriter = new StringWriter();
xmlSerializer.setOutput(stringWriter);
- if (DEBUG_PERSISTER) xmlSerializer.setFeature(
+ if (DEBUG) xmlSerializer.setFeature(
"http://xmlpull.org/v1/doc/features.html#indent-output", true);
// save task
@@ -367,7 +341,7 @@
for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) {
File taskFile = recentFiles[taskNdx];
- if (DEBUG_PERSISTER) Slog.d(TAG, "restoreTasksLocked: taskFile=" + taskFile.getName());
+ if (DEBUG) Slog.d(TAG, "restoreTasksLocked: taskFile=" + taskFile.getName());
BufferedReader reader = null;
boolean deleteFile = false;
try {
@@ -380,12 +354,11 @@
event != XmlPullParser.END_TAG) {
final String name = in.getName();
if (event == XmlPullParser.START_TAG) {
- if (DEBUG_PERSISTER)
- Slog.d(TAG, "restoreTasksLocked: START_TAG name=" + name);
+ if (DEBUG) Slog.d(TAG, "restoreTasksLocked: START_TAG name=" + name);
if (TAG_TASK.equals(name)) {
final TaskRecord task =
TaskRecord.restoreFromXml(in, mStackSupervisor);
- if (DEBUG_PERSISTER) Slog.d(TAG, "restoreTasksLocked: restored task=" +
+ if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
task);
if (task != null) {
task.isPersistable = true;
@@ -414,15 +387,14 @@
deleteFile = true;
} finally {
IoUtils.closeQuietly(reader);
- if (!DEBUG_PERSISTER && deleteFile) {
- if (true || DEBUG_PERSISTER)
- Slog.d(TAG, "Deleting file=" + taskFile.getName());
+ if (deleteFile) {
+ if (DEBUG) Slog.d(TAG, "Deleting file=" + taskFile.getName());
taskFile.delete();
}
}
}
- if (!DEBUG_PERSISTER) {
+ if (!DEBUG) {
removeObsoleteFiles(recoveredTaskIds);
}
@@ -453,8 +425,8 @@
}
private static void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, File[] files) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds="
- + persistentTaskIds + " files=" + files);
+ if (DEBUG) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds=" + persistentTaskIds +
+ " files=" + files);
if (files == null) {
Slog.e(TAG, "File error accessing recents directory (too many files open?).");
return;
@@ -467,15 +439,14 @@
final int taskId;
try {
taskId = Integer.valueOf(filename.substring(0, taskIdEnd));
- if (DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
+ if (DEBUG) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
} catch (Exception e) {
Slog.wtf(TAG, "removeObsoleteFile: Can't parse file=" + file.getName());
file.delete();
continue;
}
if (!persistentTaskIds.contains(taskId)) {
- if (true || DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: deleting file=" +
- file.getName());
+ if (DEBUG) Slog.d(TAG, "removeObsoleteFile: deleting file=" + file.getName());
file.delete();
}
}
@@ -488,441 +459,10 @@
}
static Bitmap restoreImage(String filename) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "restoreImage: restoring " + filename);
+ if (DEBUG) Slog.d(TAG, "restoreImage: restoring " + filename);
return BitmapFactory.decodeFile(sImagesDir + File.separator + filename);
}
- /**
- * Tries to restore task that were backed-up on a different device onto this device.
- */
- void restoreTasksFromOtherDeviceLocked() {
- readOtherDeviceTasksFromDisk();
- addOtherDeviceTasksToRecentsLocked();
- }
-
- /**
- * Read the tasks that were backed-up on a different device and can be restored to this device
- * from disk and populated {@link #mOtherDeviceTasksMap} with the information. Also sets up
- * time to clear out other device tasks that have not been restored on this device
- * within the allotted time.
- */
- private void readOtherDeviceTasksFromDisk() {
- synchronized (mOtherDeviceTasksMap) {
- // Clear out current map and expiration time.
- mOtherDeviceTasksMap.clear();
- mExpiredTasksCleanupTime = Long.MAX_VALUE;
-
- final File[] taskFiles;
- if (!sRestoredTasksDir.exists()
- || (taskFiles = sRestoredTasksDir.listFiles()) == null) {
- // Nothing to do if there are no tasks to restore.
- return;
- }
-
- long earliestMtime = System.currentTimeMillis();
- SparseArray<List<OtherDeviceTask>> tasksByAffiliateIds =
- new SparseArray<>(taskFiles.length);
-
- // Read new tasks from disk
- for (int i = 0; i < taskFiles.length; ++i) {
- final File taskFile = taskFiles[i];
- if (DEBUG_RESTORER) Slog.d(TAG, "readOtherDeviceTasksFromDisk: taskFile="
- + taskFile.getName());
-
- final OtherDeviceTask task = OtherDeviceTask.createFromFile(taskFile);
-
- if (task == null) {
- // Go ahead and remove the file on disk if we are unable to create a task from
- // it.
- if (DEBUG_RESTORER) Slog.e(TAG, "Unable to create task for file="
- + taskFile.getName() + "...deleting file.");
- taskFile.delete();
- continue;
- }
-
- List<OtherDeviceTask> tasks = tasksByAffiliateIds.get(task.mAffiliatedTaskId);
- if (tasks == null) {
- tasks = new ArrayList<>();
- tasksByAffiliateIds.put(task.mAffiliatedTaskId, tasks);
- }
- tasks.add(task);
- final long taskMtime = taskFile.lastModified();
- if (earliestMtime > taskMtime) {
- earliestMtime = taskMtime;
- }
- }
-
- if (tasksByAffiliateIds.size() > 0) {
- // Sort each affiliated tasks chain by taskId which is the order they were created
- // that should always be correct...Then add to task map.
- for (int i = 0; i < tasksByAffiliateIds.size(); i++) {
- List<OtherDeviceTask> chain = tasksByAffiliateIds.valueAt(i);
- Collections.sort(chain);
- // Package name of the root task in the affiliate chain.
- final String packageName =
- chain.get(chain.size()-1).mComponentName.getPackageName();
- List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.get(packageName);
- if (chains == null) {
- chains = new ArrayList<>();
- mOtherDeviceTasksMap.put(packageName, chains);
- }
- chains.add(chain);
- }
-
- // Set expiration time.
- mExpiredTasksCleanupTime = earliestMtime + MAX_INSTALL_WAIT_TIME;
- if (DEBUG_RESTORER) Slog.d(TAG, "Set Expiration time to "
- + DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
- DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
- }
- }
- }
-
- /**
- * Removed any expired tasks from {@link #mOtherDeviceTasksMap} and disk if their expiration
- * time is less than or equal to {@link #mExpiredTasksCleanupTime}.
- */
- private void removeExpiredTasksIfNeeded() {
- synchronized (mOtherDeviceTasksMap) {
- final long now = System.currentTimeMillis();
- final boolean noMoreTasks = mOtherDeviceTasksMap.isEmpty();
- if (noMoreTasks || now < mExpiredTasksCleanupTime) {
- if (noMoreTasks && mPackageUidMap != null) {
- // All done! package->uid map no longer needed.
- mPackageUidMap = null;
- }
- return;
- }
-
- long earliestNonExpiredMtime = now;
- mExpiredTasksCleanupTime = Long.MAX_VALUE;
-
- // Remove expired backed-up tasks that have not been restored. We only want to
- // remove task if it is safe to remove all tasks in the affiliation chain.
- for (int i = mOtherDeviceTasksMap.size() - 1; i >= 0 ; i--) {
-
- List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.valueAt(i);
- for (int j = chains.size() - 1; j >= 0 ; j--) {
-
- List<OtherDeviceTask> chain = chains.get(j);
- boolean removeChain = true;
- for (int k = chain.size() - 1; k >= 0 ; k--) {
- OtherDeviceTask task = chain.get(k);
- final long taskLastModified = task.mFile.lastModified();
- if ((taskLastModified + MAX_INSTALL_WAIT_TIME) > now) {
- // File has not expired yet...but we keep looping to get the earliest
- // mtime.
- if (earliestNonExpiredMtime > taskLastModified) {
- earliestNonExpiredMtime = taskLastModified;
- }
- removeChain = false;
- }
- }
- if (removeChain) {
- for (int k = chain.size() - 1; k >= 0; k--) {
- final File file = chain.get(k).mFile;
- if (DEBUG_RESTORER) Slog.d(TAG, "Deleting expired file="
- + file.getName() + " mapped to not installed component="
- + chain.get(k).mComponentName);
- file.delete();
- }
- chains.remove(j);
- }
- }
- if (chains.isEmpty()) {
- final String packageName = mOtherDeviceTasksMap.keyAt(i);
- mOtherDeviceTasksMap.removeAt(i);
- if (DEBUG_RESTORER) Slog.d(TAG, "Removed package=" + packageName
- + " from task map");
- }
- }
-
- // Reset expiration time if there is any task remaining.
- if (!mOtherDeviceTasksMap.isEmpty()) {
- mExpiredTasksCleanupTime = earliestNonExpiredMtime + MAX_INSTALL_WAIT_TIME;
- if (DEBUG_RESTORER) Slog.d(TAG, "Reset expiration time to "
- + DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
- DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
- } else {
- // All done! package->uid map no longer needed.
- mPackageUidMap = null;
- }
- }
- }
-
- /**
- * Removes the input package name from the local package->uid map.
- */
- void removeFromPackageCache(String packageName) {
- synchronized (mOtherDeviceTasksMap) {
- if (mPackageUidMap != null) {
- mPackageUidMap.remove(packageName);
- }
- }
- }
-
- /**
- * Tries to add all backed-up tasks from another device to this device recent's list.
- */
- private void addOtherDeviceTasksToRecentsLocked() {
- synchronized (mOtherDeviceTasksMap) {
- for (int i = mOtherDeviceTasksMap.size() - 1; i >= 0; i--) {
- addOtherDeviceTasksToRecentsLocked(mOtherDeviceTasksMap.keyAt(i));
- }
- }
- }
-
- /**
- * Tries to add backed-up tasks that are associated with the input package from
- * another device to this device recent's list.
- */
- void addOtherDeviceTasksToRecentsLocked(String packageName) {
- synchronized (mOtherDeviceTasksMap) {
- List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.get(packageName);
- if (chains == null) {
- return;
- }
-
- for (int i = chains.size() - 1; i >= 0; i--) {
- List<OtherDeviceTask> chain = chains.get(i);
- if (!canAddOtherDeviceTaskChain(chain)) {
- if (DEBUG_RESTORER) Slog.d(TAG, "Can't add task chain at index=" + i
- + " for package=" + packageName);
- continue;
- }
-
- // Generate task records for this chain.
- List<TaskRecord> tasks = new ArrayList<>();
- TaskRecord prev = null;
- for (int j = chain.size() - 1; j >= 0; j--) {
- TaskRecord task = createTaskRecordLocked(chain.get(j));
- if (task == null) {
- // There was a problem in creating one of this task records in this chain.
- // There is no way we can continue...
- if (DEBUG_RESTORER) Slog.d(TAG, "Can't create task record for file="
- + chain.get(j).mFile + " for package=" + packageName);
- break;
- }
-
- // Wire-up affiliation chain.
- if (prev == null) {
- task.mPrevAffiliate = null;
- task.mPrevAffiliateTaskId = INVALID_TASK_ID;
- task.mAffiliatedTaskId = task.taskId;
- } else {
- prev.mNextAffiliate = task;
- prev.mNextAffiliateTaskId = task.taskId;
- task.mAffiliatedTaskId = prev.mAffiliatedTaskId;
- task.mPrevAffiliate = prev;
- task.mPrevAffiliateTaskId = prev.taskId;
- }
- prev = task;
- tasks.add(0, task);
- }
-
- // Add tasks to recent's if we were able to create task records for all the tasks
- // in the chain.
- if (tasks.size() == chain.size()) {
- // Make sure there is space in recent's to add the new task. If there is space
- // to the to the back.
- // TODO: Would be more fancy to interleave the new tasks into recent's based on
- // {@link TaskRecord.mLastTimeMoved} and drop the oldest recent's vs. just
- // adding to the back of the list.
- int spaceLeft =
- ActivityManager.getMaxRecentTasksStatic() - mRecentTasks.size();
- if (spaceLeft >= tasks.size()) {
- mRecentTasks.addAll(mRecentTasks.size(), tasks);
- for (int k = tasks.size() - 1; k >= 0; k--) {
- // Persist new tasks.
- wakeup(tasks.get(k), false);
- }
-
- if (DEBUG_RESTORER) Slog.d(TAG, "Added " + tasks.size()
- + " tasks to recent's for" + " package=" + packageName);
- } else {
- if (DEBUG_RESTORER) Slog.d(TAG, "Didn't add to recents. tasks.size("
- + tasks.size() + ") != chain.size(" + chain.size()
- + ") for package=" + packageName);
- }
- } else {
- if (DEBUG_RESTORER) Slog.v(TAG, "Unable to add restored tasks to recents "
- + tasks.size() + " tasks for package=" + packageName);
- }
-
- // Clean-up structures
- for (int j = chain.size() - 1; j >= 0; j--) {
- chain.get(j).mFile.delete();
- }
- chains.remove(i);
- if (chains.isEmpty()) {
- // The fate of all backed-up tasks associated with this package has been
- // determine. Go ahead and remove it from the to-process list.
- mOtherDeviceTasksMap.remove(packageName);
- if (DEBUG_RESTORER)
- Slog.d(TAG, "Removed package=" + packageName + " from restore map");
- }
- }
- }
- }
-
- /**
- * Creates and returns {@link TaskRecord} for the task from another device that can be used on
- * this device. Returns null if the operation failed.
- */
- private TaskRecord createTaskRecordLocked(OtherDeviceTask other) {
- File file = other.mFile;
- BufferedReader reader = null;
- TaskRecord task = null;
- if (DEBUG_RESTORER) Slog.d(TAG, "createTaskRecordLocked: file=" + file.getName());
-
- try {
- reader = new BufferedReader(new FileReader(file));
- final XmlPullParser in = Xml.newPullParser();
- in.setInput(reader);
-
- int event;
- while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
- && event != XmlPullParser.END_TAG) {
- final String name = in.getName();
- if (event == XmlPullParser.START_TAG) {
-
- if (TAG_TASK.equals(name)) {
- // Create a task record using a task id that is valid for this device.
- task = TaskRecord.restoreFromXml(
- in, mStackSupervisor, mStackSupervisor.getNextTaskId());
- if (DEBUG_RESTORER)
- Slog.d(TAG, "createTaskRecordLocked: restored task=" + task);
-
- if (task != null) {
- task.isPersistable = true;
- task.inRecents = true;
- // Task can/should only be backed-up/restored for device owner.
- task.userId = UserHandle.USER_OWNER;
- // Clear out affiliated ids that are no longer valid on this device.
- task.mAffiliatedTaskId = INVALID_TASK_ID;
- task.mPrevAffiliateTaskId = INVALID_TASK_ID;
- task.mNextAffiliateTaskId = INVALID_TASK_ID;
- // Set up uids valid for this device.
- Integer uid = mPackageUidMap.get(task.realActivity.getPackageName());
- if (uid == null) {
- // How did this happen???
- Slog.wtf(TAG, "Can't find uid for task=" + task
- + " in mPackageUidMap=" + mPackageUidMap);
- return null;
- }
- task.effectiveUid = task.mCallingUid = uid;
- for (int i = task.mActivities.size() - 1; i >= 0; --i) {
- final ActivityRecord activity = task.mActivities.get(i);
- uid = mPackageUidMap.get(activity.launchedFromPackage);
- if (uid == null) {
- // How did this happen??
- Slog.wtf(TAG, "Can't find uid for activity=" + activity
- + " in mPackageUidMap=" + mPackageUidMap);
- return null;
- }
- activity.launchedFromUid = uid;
- }
-
- } else {
- Slog.e(TAG, "Unable to create task for backed-up file=" + file + ": "
- + fileToString(file));
- }
- } else {
- Slog.wtf(TAG, "createTaskRecordLocked Unknown xml event=" + event
- + " name=" + name);
- }
- }
- XmlUtils.skipCurrentTag(in);
- }
- } catch (Exception e) {
- Slog.wtf(TAG, "Unable to parse " + file + ". Error ", e);
- Slog.e(TAG, "Failing file: " + fileToString(file));
- } finally {
- IoUtils.closeQuietly(reader);
- }
-
- return task;
- }
-
- /**
- * Returns true if the input task chain backed-up from another device can be restored on this
- * device. Also, sets the {@link OtherDeviceTask#mUid} on the input tasks if they can be
- * restored.
- */
- private boolean canAddOtherDeviceTaskChain(List<OtherDeviceTask> chain) {
-
- final ArraySet<ComponentName> validComponents = new ArraySet<>();
- final IPackageManager pm = AppGlobals.getPackageManager();
- for (int i = 0; i < chain.size(); i++) {
-
- OtherDeviceTask task = chain.get(i);
- // Quick check, we can't add the task chain if any of its task files don't exist.
- if (!task.mFile.exists()) {
- if (DEBUG_RESTORER) Slog.d(TAG,
- "Can't add chain due to missing file=" + task.mFile);
- return false;
- }
-
- // Verify task package is installed.
- if (!isPackageInstalled(task.mComponentName.getPackageName())) {
- return false;
- }
- // Verify that all the launch packages are installed.
- if (task.mLaunchPackages != null) {
- for (int j = task.mLaunchPackages.size() - 1; j >= 0; --j) {
- if (!isPackageInstalled(task.mLaunchPackages.valueAt(j))) {
- return false;
- }
- }
- }
-
- if (validComponents.contains(task.mComponentName)) {
- // Existance of component has already been verified.
- continue;
- }
-
- // Check to see if the specific component is installed.
- try {
- if (pm.getActivityInfo(task.mComponentName, 0, UserHandle.USER_OWNER) == null) {
- // Component isn't installed...
- return false;
- }
- validComponents.add(task.mComponentName);
- } catch (RemoteException e) {
- // Should not happen???
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Returns true if the input package name is installed. If the package is installed, an entry
- * for the package is added to {@link #mPackageUidMap}.
- */
- private boolean isPackageInstalled(final String packageName) {
- if (mPackageUidMap != null && mPackageUidMap.containsKey(packageName)) {
- return true;
- }
- try {
- int uid = AppGlobals.getPackageManager().getPackageUid(
- packageName, UserHandle.USER_OWNER);
- if (uid == -1) {
- // package doesn't exist...
- return false;
- }
- if (mPackageUidMap == null) {
- mPackageUidMap = new ArrayMap<>();
- }
- mPackageUidMap.put(packageName, uid);
- return true;
- } catch (RemoteException e) {
- // Should not happen???
- return false;
- }
- }
-
private class LazyTaskWriterThread extends Thread {
LazyTaskWriterThread(String name) {
@@ -941,21 +481,20 @@
probablyDone = mWriteQueue.isEmpty();
}
if (probablyDone) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "Looking for obsolete files.");
+ if (DEBUG) Slog.d(TAG, "Looking for obsolete files.");
persistentTaskIds.clear();
synchronized (mService) {
- if (DEBUG_PERSISTER) Slog.d(TAG, "mRecents=" + mRecentTasks);
+ if (DEBUG) Slog.d(TAG, "mRecents=" + mRecentTasks);
for (int taskNdx = mRecentTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mRecentTasks.get(taskNdx);
- if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: task=" + task +
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
" persistable=" + task.isPersistable);
if ((task.isPersistable || task.inRecents)
&& (task.stack == null || !task.stack.isHomeStack())) {
- if (DEBUG_PERSISTER)
- Slog.d(TAG, "adding to persistentTaskIds task=" + task);
+ if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
persistentTaskIds.add(task.taskId);
} else {
- if (DEBUG_PERSISTER) Slog.d(TAG,
+ if (DEBUG) Slog.d(TAG,
"omitting from persistentTaskIds task=" + task);
}
}
@@ -969,7 +508,7 @@
if (mNextWriteTime != FLUSH_QUEUE) {
// The next write we don't have to wait so long.
mNextWriteTime = SystemClock.uptimeMillis() + INTER_WRITE_DELAY_MS;
- if (DEBUG_PERSISTER) Slog.d(TAG, "Next write time may be in " +
+ if (DEBUG) Slog.d(TAG, "Next write time may be in " +
INTER_WRITE_DELAY_MS + " msec. (" + mNextWriteTime + ")");
}
@@ -979,13 +518,8 @@
mNextWriteTime = 0; // idle.
TaskPersister.this.notifyAll(); // wake up flush() if needed.
}
-
- // See if we need to remove any expired back-up tasks before waiting.
- removeExpiredTasksIfNeeded();
-
try {
- if (DEBUG_PERSISTER)
- Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
TaskPersister.this.wait();
} catch (InterruptedException e) {
}
@@ -995,12 +529,11 @@
item = mWriteQueue.remove(0);
long now = SystemClock.uptimeMillis();
- if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: now=" + now
- + " mNextWriteTime=" + mNextWriteTime + " mWriteQueue.size="
- + mWriteQueue.size());
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: now=" + now + " mNextWriteTime=" +
+ mNextWriteTime + " mWriteQueue.size=" + mWriteQueue.size());
while (now < mNextWriteTime) {
try {
- if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: waiting " +
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting " +
(mNextWriteTime - now));
TaskPersister.this.wait(mNextWriteTime - now);
} catch (InterruptedException e) {
@@ -1015,7 +548,7 @@
ImageWriteQueueItem imageWriteQueueItem = (ImageWriteQueueItem) item;
final String filename = imageWriteQueueItem.mFilename;
final Bitmap bitmap = imageWriteQueueItem.mImage;
- if (DEBUG_PERSISTER) Slog.d(TAG, "writing bitmap: filename=" + filename);
+ if (DEBUG) Slog.d(TAG, "writing bitmap: filename=" + filename);
FileOutputStream imageFile = null;
try {
imageFile = new FileOutputStream(new File(sImagesDir, filename));
@@ -1029,12 +562,12 @@
// Write out one task.
StringWriter stringWriter = null;
TaskRecord task = ((TaskWriteQueueItem) item).mTask;
- if (DEBUG_PERSISTER) Slog.d(TAG, "Writing task=" + task);
+ if (DEBUG) Slog.d(TAG, "Writing task=" + task);
synchronized (mService) {
if (task.inRecents) {
// Still there.
try {
- if (DEBUG_PERSISTER) Slog.d(TAG, "Saving task=" + task);
+ if (DEBUG) Slog.d(TAG, "Saving task=" + task);
stringWriter = saveToXml(task);
} catch (IOException e) {
} catch (XmlPullParserException e) {
@@ -1064,127 +597,4 @@
}
}
}
-
- /**
- * Helper class for holding essential information about task that were backed-up on a different
- * device that can be restored on this device.
- */
- private static class OtherDeviceTask implements Comparable<OtherDeviceTask> {
- final File mFile;
- // See {@link TaskRecord} for information on the fields below.
- final ComponentName mComponentName;
- final int mTaskId;
- final int mAffiliatedTaskId;
-
- // Names of packages that launched activities in this task. All packages listed here need
- // to be installed on the current device in order for the task to be restored successfully.
- final ArraySet<String> mLaunchPackages;
-
- private OtherDeviceTask(File file, ComponentName componentName, int taskId,
- int affiliatedTaskId, ArraySet<String> launchPackages) {
- mFile = file;
- mComponentName = componentName;
- mTaskId = taskId;
- mAffiliatedTaskId = (affiliatedTaskId == INVALID_TASK_ID) ? taskId: affiliatedTaskId;
- mLaunchPackages = launchPackages;
- }
-
- @Override
- public int compareTo(OtherDeviceTask another) {
- return mTaskId - another.mTaskId;
- }
-
- /**
- * Creates a new {@link OtherDeviceTask} object based on the contents of the input file.
- *
- * @param file input file that contains the complete task information.
- * @return new {@link OtherDeviceTask} object or null if we failed to create the object.
- */
- static OtherDeviceTask createFromFile(File file) {
- if (file == null || !file.exists()) {
- if (DEBUG_RESTORER)
- Slog.d(TAG, "createFromFile: file=" + file + " doesn't exist.");
- return null;
- }
-
- BufferedReader reader = null;
-
- try {
- reader = new BufferedReader(new FileReader(file));
- final XmlPullParser in = Xml.newPullParser();
- in.setInput(reader);
-
- int event;
- while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
- event != XmlPullParser.START_TAG) {
- // Skip to the start tag or end of document
- }
-
- if (event == XmlPullParser.START_TAG) {
- final String name = in.getName();
-
- if (TAG_TASK.equals(name)) {
- final int outerDepth = in.getDepth();
- ComponentName componentName = null;
- int taskId = INVALID_TASK_ID;
- int taskAffiliation = INVALID_TASK_ID;
- for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
- final String attrName = in.getAttributeName(j);
- final String attrValue = in.getAttributeValue(j);
- if (TaskRecord.ATTR_REALACTIVITY.equals(attrName)) {
- componentName = ComponentName.unflattenFromString(attrValue);
- } else if (TaskRecord.ATTR_TASKID.equals(attrName)) {
- taskId = Integer.valueOf(attrValue);
- } else if (TaskRecord.ATTR_TASK_AFFILIATION.equals(attrName)) {
- taskAffiliation = Integer.valueOf(attrValue);
- }
- }
- if (componentName == null || taskId == INVALID_TASK_ID) {
- if (DEBUG_RESTORER) Slog.e(TAG,
- "createFromFile: FAILED componentName=" + componentName
- + " taskId=" + taskId + " file=" + file);
- return null;
- }
-
- ArraySet<String> launchPackages = null;
- while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
- (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
- if (event == XmlPullParser.START_TAG) {
- if (TaskRecord.TAG_ACTIVITY.equals(in.getName())) {
- for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
- if (ActivityRecord.ATTR_LAUNCHEDFROMPACKAGE.equals(
- in.getAttributeName(j))) {
- if (launchPackages == null) {
- launchPackages = new ArraySet();
- }
- launchPackages.add(in.getAttributeValue(j));
- }
- }
- } else {
- XmlUtils.skipCurrentTag(in);
- }
- }
- }
- if (DEBUG_RESTORER) Slog.d(TAG, "creating OtherDeviceTask from file="
- + file.getName() + " componentName=" + componentName
- + " taskId=" + taskId + " launchPackages=" + launchPackages);
- return new OtherDeviceTask(file, componentName, taskId,
- taskAffiliation, launchPackages);
- } else {
- Slog.wtf(TAG,
- "createFromFile: Unknown xml event=" + event + " name=" + name);
- }
- } else {
- Slog.wtf(TAG, "createFromFile: Unable to find start tag in file=" + file);
- }
- } catch (IOException | XmlPullParserException e) {
- Slog.wtf(TAG, "Unable to parse " + file + ". Error ", e);
- } finally {
- IoUtils.closeQuietly(reader);
- }
-
- // Something went wrong...
- return null;
- }
- }
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f653e9e..417c7c3 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -28,8 +28,6 @@
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
-import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
-import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
import android.app.Activity;
import android.app.ActivityManager;
@@ -71,7 +69,7 @@
private static final String TAG_AFFINITYINTENT = "affinity_intent";
static final String ATTR_REALACTIVITY = "real_activity";
private static final String ATTR_ORIGACTIVITY = "orig_activity";
- static final String TAG_ACTIVITY = "activity";
+ private static final String TAG_ACTIVITY = "activity";
private static final String ATTR_AFFINITY = "affinity";
private static final String ATTR_ROOT_AFFINITY = "root_affinity";
private static final String ATTR_ROOTHASRESET = "root_has_reset";
@@ -970,10 +968,6 @@
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
throws IOException, XmlPullParserException {
- return restoreFromXml(in, stackSupervisor, INVALID_TASK_ID);
- }
- static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor,
- int inTaskId) throws IOException, XmlPullParserException {
Intent intent = null;
Intent affinityIntent = null;
ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
@@ -993,7 +987,7 @@
long lastActiveTime = -1;
long lastTimeOnTop = 0;
boolean neverRelinquishIdentity = true;
- int taskId = inTaskId;
+ int taskId = INVALID_TASK_ID;
final int outerDepth = in.getDepth();
TaskDescription taskDescription = new TaskDescription();
int taskAffiliation = INVALID_TASK_ID;
@@ -1008,8 +1002,8 @@
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
final String attrName = in.getAttributeName(attrNdx);
final String attrValue = in.getAttributeValue(attrNdx);
- if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
- "TaskRecord: attribute name=" + attrName + " value=" + attrValue);
+ if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
+ attrName + " value=" + attrValue);
if (ATTR_TASKID.equals(attrName)) {
if (taskId == INVALID_TASK_ID) taskId = Integer.valueOf(attrValue);
} else if (ATTR_REALACTIVITY.equals(attrName)) {
@@ -1071,16 +1065,16 @@
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
- if (DEBUG_PERSISTER || DEBUG_RESTORER)
- Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" + name);
+ if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
+ name);
if (TAG_AFFINITYINTENT.equals(name)) {
affinityIntent = Intent.restoreFromXml(in);
} else if (TAG_INTENT.equals(name)) {
intent = Intent.restoreFromXml(in);
} else if (TAG_ACTIVITY.equals(name)) {
ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor);
- if (DEBUG_PERSISTER || DEBUG_RESTORER)
- Slog.d(TaskPersister.TAG, "TaskRecord: activity=" + activity);
+ if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
+ activity);
if (activity != null) {
activities.add(activity);
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 75198e5..dbfd4ef 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -42,6 +42,14 @@
private static final EnumMap<SupplicantState, DetailedState> stateMap =
new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);
+ /**
+ * Default MAC address reported to a client that does not have the
+ * android.permission.LOCAL_MAC_ADDRESS permission.
+ *
+ * @hide
+ */
+ public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
+
static {
stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
@@ -91,7 +99,7 @@
private int mFrequency;
private InetAddress mIpAddress;
- private String mMacAddress;
+ private String mMacAddress = DEFAULT_MAC_ADDRESS;
/**
* @hide