Merge "Merge "Docs: Removed note in "Platform Versions" section" into mnc-io-docs am: 9dfa75ef43 am: 202017dcbf am: 2c69d1ecae am: f986b700de" into nyc-mr1-dev-plus-aosp
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0cc44e7..e108dd6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4323,18 +4323,23 @@
// experience
bigTextText = mBuilder.processLegacyText(text);
}
- contentView.setTextViewText(R.id.big_text, bigTextText);
- contentView.setViewVisibility(R.id.big_text,
- TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
- contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines());
- contentView.setBoolean(R.id.big_text, "setHasImage", mBuilder.mN.mLargeIcon != null);
+ applyBigTextContentView(mBuilder, contentView, bigTextText);
return contentView;
}
- private int calculateMaxLines() {
+ static void applyBigTextContentView(Builder builder,
+ RemoteViews contentView, CharSequence bigTextText) {
+ contentView.setTextViewText(R.id.big_text, bigTextText);
+ contentView.setViewVisibility(R.id.big_text,
+ TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
+ contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines(builder));
+ contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.mLargeIcon != null);
+ }
+
+ private static int calculateMaxLines(Builder builder) {
int lineCount = MAX_LINES;
- boolean hasActions = mBuilder.mActions.size() > 0;
+ boolean hasActions = builder.mActions.size() > 0;
if (hasActions) {
lineCount -= LINES_CONSUMED_BY_ACTIONS;
}
@@ -4532,6 +4537,16 @@
: mConversationTitle;
boolean hasTitle = !TextUtils.isEmpty(title);
+ if (!hasTitle && mMessages.size() == 1) {
+ CharSequence sender = mMessages.get(0).mSender;
+ CharSequence text = mMessages.get(0).mText;
+ RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
+ mBuilder.getBigTextLayoutResource(),
+ false /* progress */, sender, null /* text */);
+ BigTextStyle.applyBigTextContentView(mBuilder, contentView, text);
+ return contentView;
+ }
+
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
false /* hasProgress */,
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 9e69f79..045f127 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -36,6 +36,13 @@
return reinterpret_cast<jlong>(tree);
}
+static jlong createTreeFromCopy(JNIEnv*, jobject, jlong treePtr, jlong groupPtr) {
+ VectorDrawable::Group* rootGroup = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
+ VectorDrawable::Tree* treeToCopy = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+ VectorDrawable::Tree* tree = new VectorDrawable::Tree(treeToCopy, rootGroup);
+ return reinterpret_cast<jlong>(tree);
+}
+
static jlong createEmptyFullPath(JNIEnv*, jobject) {
VectorDrawable::FullPath* newPath = new VectorDrawable::FullPath();
return reinterpret_cast<jlong>(newPath);
@@ -344,6 +351,7 @@
static const JNINativeMethod gMethods[] = {
{"nCreateTree", "!(J)J", (void*)createTree},
+ {"nCreateTreeFromCopy", "!(JJ)J", (void*)createTreeFromCopy},
{"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize},
{"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha},
{"nGetRootAlpha", "!(J)F", (void*)getRootAlpha},
diff --git a/core/res/res/layout/app_error_dialog.xml b/core/res/res/layout/app_error_dialog.xml
index 7147ea2..9a5bbd4 100644
--- a/core/res/res/layout/app_error_dialog.xml
+++ b/core/res/res/layout/app_error_dialog.xml
@@ -35,11 +35,11 @@
/>
<Button
- android:id="@+id/aerr_reset"
+ android:id="@+id/aerr_close"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/aerr_reset"
- android:drawableStart="@drawable/ic_refresh"
+ android:text="@string/aerr_close"
+ android:drawableStart="@drawable/ic_close"
style="@style/aerr_list_item"
/>
@@ -53,15 +53,6 @@
/>
<Button
- android:id="@+id/aerr_close"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/aerr_close"
- android:drawableStart="@drawable/ic_close"
- style="@style/aerr_list_item"
- />
-
- <Button
android:id="@+id/aerr_mute"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 236940d..3a28822 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2725,9 +2725,7 @@
<!-- Text of the alert that is displayed when a process has crashed repeatedly. -->
<string name="aerr_process_repeated"><xliff:g id="process">%1$s</xliff:g> keeps stopping</string>
<!-- Button that restarts a crashed application -->
- <string name="aerr_restart">Restart app</string>
- <!-- Button that clears cache and restarts a crashed application -->
- <string name="aerr_reset">Reset and restart app</string>
+ <string name="aerr_restart">Open app again</string>
<!-- Button that sends feedback about a crashed application -->
<string name="aerr_report">Send feedback</string>
<!-- Button that closes a crashed application -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 115c49f..0f20b5c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2446,7 +2446,6 @@
<java-symbol type="id" name="work_widget_badge_icon" />
<java-symbol type="id" name="aerr_report" />
- <java-symbol type="id" name="aerr_reset" />
<java-symbol type="id" name="aerr_restart" />
<java-symbol type="id" name="aerr_close" />
<java-symbol type="id" name="aerr_mute" />
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index dd33e98..f5592fa 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -804,7 +804,7 @@
mTintMode = copy.mTintMode;
mAutoMirrored = copy.mAutoMirrored;
mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
- createNativeTree(mRootGroup);
+ createNativeTreeFromCopy(copy, mRootGroup);
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
@@ -826,6 +826,16 @@
VMRuntime.getRuntime().registerNativeAllocation(NATIVE_ALLOCATION_SIZE);
}
+ // Create a new native tree with the given root group, and copy the properties from the
+ // given VectorDrawableState's native tree.
+ private void createNativeTreeFromCopy(VectorDrawableState copy, VGroup rootGroup) {
+ mNativeTree = new VirtualRefBasePtr(nCreateTreeFromCopy(
+ copy.mNativeTree.get(), rootGroup.mNativePtr));
+ // Register tree size
+ VMRuntime.getRuntime().registerNativeAllocation(NATIVE_ALLOCATION_SIZE);
+ }
+
+
void onTreeConstructionFinished() {
mRootGroup.setTree(mNativeTree);
mAllocationOfAllNodes = mRootGroup.getNativeSize();
@@ -1777,6 +1787,7 @@
}
private static native long nCreateTree(long rootGroupPtr);
+ private static native long nCreateTreeFromCopy(long treeToCopy, long rootGroupPtr);
private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
float viewportHeight);
private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f0348e4..2b79941 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -530,7 +530,7 @@
if (prop->getRootAlpha() == 1.0f && prop->getColorFilter() == nullptr) {
return nullptr;
} else {
- outPaint->setColorFilter(mStagingProperties.getColorFilter());
+ outPaint->setColorFilter(prop->getColorFilter());
outPaint->setFilterQuality(kLow_SkFilterQuality);
outPaint->setAlpha(prop->getRootAlpha() * 255);
return outPaint;
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index b33f26c..a5d1d4b 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -542,6 +542,12 @@
Tree(Group* rootNode) : mRootNode(rootNode) {
mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
}
+
+ // Copy properties from the tree and use the give node as the root node
+ Tree(const Tree* copy, Group* rootNode) : Tree(rootNode) {
+ mStagingProperties.syncAnimatableProperties(*copy->stagingProperties());
+ mStagingProperties.syncNonAnimatableProperties(*copy->stagingProperties());
+ }
// Draws the VD onto a bitmap cache, then the bitmap cache will be rendered onto the input
// canvas. Returns the number of pixels needed for the bitmap cache.
int draw(Canvas* outCanvas, SkColorFilter* colorFilter,
@@ -666,7 +672,7 @@
};
void onPropertyChanged(TreeProperties* prop);
TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
- const TreeProperties* stagingProperties() { return &mStagingProperties; }
+ const TreeProperties* stagingProperties() const { return &mStagingProperties; }
PushStagingFunctor* getFunctor() { return &mFunctor;}
// This should only be called from animations on RT
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
index 423c3b0..a8b782e8 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
@@ -37,6 +37,7 @@
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.ImageReader;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
@@ -127,6 +128,7 @@
protected List<Size> mOrderedRAW10Sizes; // In descending order.
protected List<Size> mOrderedYUV420888Sizes; // In descending order.
protected HashMap<Size, Long> mMinPreviewFrameDurationMap;
+ protected boolean mSupportRAW10;
protected WindowManager mWindowManager;
@@ -603,16 +605,21 @@
mCamera = CameraTestUtils.openCamera(
mCameraManager, cameraId, mCameraListener, mHandler);
mCollector.setCameraId(cameraId);
- mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
- CheckLevel.ASSERT, /*collector*/null);
+ CameraCharacteristics properties = mCameraManager.getCameraCharacteristics(cameraId);
+ mStaticInfo = new StaticMetadata(properties, CheckLevel.ASSERT, /*collector*/null);
+ StreamConfigurationMap configMap =
+ properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ mSupportRAW10 = configMap.isOutputSupportedFor(ImageFormat.RAW10);
if (mStaticInfo.isColorOutputSupported()) {
mOrderedPreviewSizes = getSupportedPreviewSizes(cameraId, mCameraManager,
getPreviewSizeBound(mWindowManager, PREVIEW_SIZE_BOUND));
mOrderedVideoSizes = getSupportedVideoSizes(
cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
- mOrderedRAW10Sizes = getSortedSizesForFormat(
- cameraId, mCameraManager, ImageFormat.RAW10, null);
+ if (mSupportRAW10) {
+ mOrderedRAW10Sizes = getSortedSizesForFormat(
+ cameraId, mCameraManager, ImageFormat.RAW10, null);
+ }
mOrderedYUV420888Sizes = getSortedSizesForFormat(
cameraId, mCameraManager, ImageFormat.YUV_420_888, null);
// Use ImageFormat.YUV_420_888 for now. TODO: need figure out what's format for preview
@@ -636,6 +643,7 @@
mOrderedPreviewSizes = null;
mOrderedVideoSizes = null;
mOrderedStillSizes = null;
+ mSupportRAW10 = false;
}
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 2a78f90..3745e0b 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -17,12 +17,10 @@
package com.android.server;
import android.Manifest.permission;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.INetworkScoreCache;
@@ -33,7 +31,6 @@
import android.net.ScoredNetwork;
import android.os.Binder;
import android.os.IBinder;
-import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
@@ -42,6 +39,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -62,39 +60,75 @@
private final Context mContext;
private final Map<Integer, INetworkScoreCache> mScoreCaches;
- /** Lock used to update mReceiver when scorer package changes occur. */
- private final Object mReceiverLock = new Object[0];
+ /** Lock used to update mPackageMonitor when scorer package changes occur. */
+ private final Object mPackageMonitorLock = new Object[0];
- /** Clears scores when the active scorer package is no longer valid. */
- @GuardedBy("mReceiverLock")
- private ScorerChangedReceiver mReceiver;
+ @GuardedBy("mPackageMonitorLock")
+ private NetworkScorerPackageMonitor mPackageMonitor;
private ScoringServiceConnection mServiceConnection;
- private class ScorerChangedReceiver extends BroadcastReceiver {
+ /**
+ * Clears scores when the active scorer package is no longer valid and
+ * manages the service connection.
+ */
+ private class NetworkScorerPackageMonitor extends PackageMonitor {
final String mRegisteredPackage;
- ScorerChangedReceiver(String packageName) {
- mRegisteredPackage = packageName;
+ private NetworkScorerPackageMonitor(String mRegisteredPackage) {
+ this.mRegisteredPackage = mRegisteredPackage;
}
@Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
- || Intent.ACTION_PACKAGE_REPLACED.equals(action)
- || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
- NetworkScorerAppData activeScorer =
+ public void onPackageAdded(String packageName, int uid) {
+ evaluateBinding(packageName, true /* forceUnbind */);
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ evaluateBinding(packageName, true /* forceUnbind */);
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ evaluateBinding(packageName, false /* forceUnbind */);
+ }
+
+ @Override
+ public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+ if (doit) { // "doit" means the force stop happened instead of just being queried for.
+ for (String packageName : packages) {
+ evaluateBinding(packageName, true /* forceUnbind */);
+ }
+ }
+ return super.onHandleForceStop(intent, packages, uid, doit);
+ }
+
+ @Override
+ public void onPackageUpdateFinished(String packageName, int uid) {
+ evaluateBinding(packageName, true /* forceUnbind */);
+ }
+
+ private void evaluateBinding(String scorerPackageName, boolean forceUnbind) {
+ if (mRegisteredPackage.equals(scorerPackageName)) {
+ if (DBG) {
+ Log.d(TAG, "Evaluating binding for: " + scorerPackageName
+ + ", forceUnbind=" + forceUnbind);
+ }
+ final NetworkScorerAppData activeScorer =
NetworkScorerAppManager.getActiveScorer(mContext);
if (activeScorer == null) {
- // Package change has invalidated a scorer.
+ // Package change has invalidated a scorer, this will also unbind any service
+ // connection.
Log.i(TAG, "Package " + mRegisteredPackage +
" is no longer valid, disabling scoring.");
setScorerInternal(null);
} else if (activeScorer.mScoringServiceClassName == null) {
// The scoring service is not available, make sure it's unbound.
unbindFromScoringServiceIfNeeded();
- } else {
- // The scoring service may have changed or been added.
+ } else { // The scoring service changed in some way.
+ if (forceUnbind) {
+ unbindFromScoringServiceIfNeeded();
+ }
bindToScoringServiceIfNeeded(activeScorer);
}
}
@@ -121,7 +155,7 @@
Settings.Global.putInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 1);
}
- registerPackageReceiverIfNeeded();
+ registerPackageMonitorIfNeeded();
}
/** Called when the system is ready for us to start third-party code. */
@@ -130,33 +164,29 @@
bindToScoringServiceIfNeeded();
}
- private void registerPackageReceiverIfNeeded() {
- if (DBG) Log.d(TAG, "registerPackageReceiverIfNeeded");
+ private void registerPackageMonitorIfNeeded() {
+ if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext);
- synchronized (mReceiverLock) {
- // Unregister the receiver if the current scorer has changed since last registration.
- if (mReceiver != null) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Unregistering receiver for " + mReceiver.mRegisteredPackage);
+ synchronized (mPackageMonitorLock) {
+ // Unregister the current monitor if needed.
+ if (mPackageMonitor != null) {
+ if (DBG) {
+ Log.d(TAG, "Unregistering package monitor for "
+ + mPackageMonitor.mRegisteredPackage);
}
- mContext.unregisterReceiver(mReceiver);
- mReceiver = null;
+ mPackageMonitor.unregister();
+ mPackageMonitor = null;
}
- // Register receiver if a scorer is active.
+ // Create and register the monitor if a scorer is active.
if (scorer != null) {
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
- filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
- filter.addDataScheme("package");
- filter.addDataSchemeSpecificPart(scorer.mPackageName,
- PatternMatcher.PATTERN_LITERAL);
- mReceiver = new ScorerChangedReceiver(scorer.mPackageName);
+ mPackageMonitor = new NetworkScorerPackageMonitor(scorer.mPackageName);
// TODO: Need to update when we support per-user scorers. http://b/23422763
- mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter, null, null);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Registered receiver for " + scorer.mPackageName);
+ mPackageMonitor.register(mContext, null /* thread */, UserHandle.SYSTEM,
+ false /* externalStorage */);
+ if (DBG) {
+ Log.d(TAG, "Registered package monitor for "
+ + mPackageMonitor.mRegisteredPackage);
}
}
}
@@ -299,7 +329,7 @@
// will be made to bind to the new scorer.
bindToScoringServiceIfNeeded();
if (result) { // new scorer successfully set
- registerPackageReceiverIfNeeded();
+ registerPackageMonitorIfNeeded();
Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
if (prevScorer != null) { // Directly notify the old scorer.
@@ -391,20 +421,24 @@
private static class ScoringServiceConnection implements ServiceConnection {
private final ComponentName mComponentName;
private boolean mBound = false;
+ private boolean mConnected = false;
ScoringServiceConnection(ComponentName componentName) {
mComponentName = componentName;
}
void connect(Context context) {
- disconnect(context);
- Intent service = new Intent();
- service.setComponent(mComponentName);
- mBound = context.bindServiceAsUser(service, this,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
- UserHandle.SYSTEM);
if (!mBound) {
- Log.w(TAG, "Bind call failed for " + service);
+ Intent service = new Intent();
+ service.setComponent(mComponentName);
+ mBound = context.bindServiceAsUser(service, this,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ UserHandle.SYSTEM);
+ if (!mBound) {
+ Log.w(TAG, "Bind call failed for " + service);
+ } else {
+ if (DBG) Log.d(TAG, "ScoringServiceConnection bound.");
+ }
}
}
@@ -413,6 +447,7 @@
if (mBound) {
mBound = false;
context.unbindService(this);
+ if (DBG) Log.d(TAG, "ScoringServiceConnection unbound.");
}
} catch (RuntimeException e) {
Log.e(TAG, "Unbind failed.", e);
@@ -422,15 +457,20 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
+ mConnected = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
- if (DBG) Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
+ if (DBG) {
+ Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
+ }
+ mConnected = false;
}
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound);
+ writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound
+ + ", connected: " + mConnected);
}
}
}
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index ddfab4d..e37feb2 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -18,13 +18,17 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.IPackageDataObserver;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.provider.Settings;
import android.text.BidiFormatter;
import android.util.Slog;
import android.view.LayoutInflater;
@@ -43,6 +47,7 @@
private final AppErrorResult mResult;
private final ProcessRecord mProc;
private final boolean mRepeating;
+ private final boolean mForeground;
private CharSequence mName;
@@ -54,9 +59,9 @@
static final int FORCE_QUIT = 1;
static final int FORCE_QUIT_AND_REPORT = 2;
static final int RESTART = 3;
- static final int RESET = 4;
static final int MUTE = 5;
static final int TIMEOUT = 6;
+ static final int CANCEL = 7;
// 5-minute timeout, then we automatically dismiss the crash dialog
static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
@@ -69,6 +74,7 @@
mProc = data.proc;
mResult = data.result;
mRepeating = data.repeating;
+ mForeground = data.task != null;
BidiFormatter bidi = BidiFormatter.getInstance();
if ((mProc.pkgList.size() == 1) &&
@@ -86,7 +92,8 @@
bidi.unicodeWrap(mName.toString())));
}
- setCancelable(false);
+ setCancelable(true);
+ setCancelMessage(mHandler.obtainMessage(CANCEL));
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.setTitle("Application Error: " + mProc.info.processName);
@@ -111,25 +118,41 @@
LayoutInflater.from(context).inflate(
com.android.internal.R.layout.app_error_dialog, frame, true);
+ boolean hasRestart = !mRepeating && mForeground;
+ final boolean hasReceiver = mProc.errorReportReceiver != null;
+
final TextView restart = (TextView) findViewById(com.android.internal.R.id.aerr_restart);
restart.setOnClickListener(this);
- restart.setVisibility(!mRepeating ? View.VISIBLE : View.GONE);
- final TextView reset = (TextView) findViewById(com.android.internal.R.id.aerr_reset);
- reset.setOnClickListener(this);
- reset.setVisibility(mRepeating ? View.VISIBLE : View.GONE);
+ restart.setVisibility(hasRestart ? View.VISIBLE : View.GONE);
final TextView report = (TextView) findViewById(com.android.internal.R.id.aerr_report);
report.setOnClickListener(this);
- final boolean hasReceiver = mProc.errorReportReceiver != null;
report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
final TextView close = (TextView) findViewById(com.android.internal.R.id.aerr_close);
+ close.setVisibility(!hasRestart ? View.VISIBLE : View.GONE);
close.setOnClickListener(this);
+
+ boolean showMute = !IS_USER_BUILD && Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
final TextView mute = (TextView) findViewById(com.android.internal.R.id.aerr_mute);
mute.setOnClickListener(this);
- mute.setVisibility(!IS_USER_BUILD ? View.VISIBLE : View.GONE);
+ mute.setVisibility(showMute ? View.VISIBLE : View.GONE);
findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
}
+ @Override
+ public void onStart() {
+ super.onStart();
+ getContext().registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ getContext().unregisterReceiver(mReceiver);
+ }
+
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
final int result = msg.what;
@@ -163,9 +186,6 @@
case com.android.internal.R.id.aerr_restart:
mHandler.obtainMessage(RESTART).sendToTarget();
break;
- case com.android.internal.R.id.aerr_reset:
- mHandler.obtainMessage(RESET).sendToTarget();
- break;
case com.android.internal.R.id.aerr_report:
mHandler.obtainMessage(FORCE_QUIT_AND_REPORT).sendToTarget();
break;
@@ -180,6 +200,15 @@
}
}
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ cancel();
+ }
+ }
+ };
+
static class Data {
AppErrorResult result;
TaskRecord task;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 3ed9969..49106f4 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -370,38 +370,9 @@
Intent appErrorIntent = null;
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
- if (res == AppErrorDialog.TIMEOUT) {
+ if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
res = AppErrorDialog.FORCE_QUIT;
}
- if (res == AppErrorDialog.RESET) {
- String[] packageList = r.getPackageList();
- if (packageList != null) {
- PackageManager pm = mContext.getPackageManager();
- final Semaphore s = new Semaphore(0);
- for (int i = 0; i < packageList.length; i++) {
- if (i < packageList.length - 1) {
- pm.deleteApplicationCacheFiles(packageList[i], null);
- } else {
- pm.deleteApplicationCacheFiles(packageList[i],
- new IPackageDataObserver.Stub() {
- @Override
- public void onRemoveCompleted(String packageName,
- boolean succeeded) {
- s.release();
- }
- });
-
- // Wait until cache has been cleared before we restart.
- try {
- s.acquire();
- } catch (InterruptedException e) {
- }
- }
- }
- }
- // If there was nothing to reset, just restart;
- res = AppErrorDialog.RESTART;
- }
synchronized (mService) {
if (res == AppErrorDialog.MUTE) {
stopReportingCrashesLocked(r);