blob: 0ff0d3353041c324ad7ddd10530870dce7fe9ab0 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.shell;
import static com.android.shell.HeapDumpProvider.makeUri;
import static com.android.shell.HeapDumpReceiver.ACTION_DELETE_HEAP_DUMP;
import static com.android.shell.HeapDumpReceiver.EXTRA_IS_USER_INITIATED;
import static com.android.shell.HeapDumpReceiver.EXTRA_PROCESS_NAME;
import static com.android.shell.HeapDumpReceiver.EXTRA_REPORT_PACKAGE;
import static com.android.shell.HeapDumpReceiver.EXTRA_SIZE_BYTES;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.util.DebugUtils;
import android.util.Log;
import com.android.internal.R;
/**
* This activity is displayed when the system has collected a heap dump.
*/
public class HeapDumpActivity extends Activity {
private static final String TAG = "HeapDumpActivity";
static final String KEY_URI = "uri";
private AlertDialog mDialog;
private Uri mDumpUri;
private boolean mHandled = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String process = getIntent().getStringExtra(EXTRA_PROCESS_NAME);
long size = getIntent().getLongExtra(EXTRA_SIZE_BYTES, 0);
final boolean isUserInitiated = getIntent().getBooleanExtra(EXTRA_IS_USER_INITIATED, false);
final int uid = getIntent().getIntExtra(Intent.EXTRA_UID, 0);
final boolean isSystemProcess = uid == Process.SYSTEM_UID;
mDumpUri = makeUri(process);
final String procDisplayName = isSystemProcess
? getString(com.android.internal.R.string.android_system_label)
: process;
final Intent sendIntent = new Intent();
ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", mDumpUri);
sendIntent.setClipData(clip);
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
sendIntent.setType(clip.getDescription().getMimeType(0));
sendIntent.putExtra(Intent.EXTRA_STREAM, mDumpUri);
String directLaunchPackage = getIntent().getStringExtra(EXTRA_REPORT_PACKAGE);
if (directLaunchPackage != null) {
sendIntent.setAction(ActivityManager.ACTION_REPORT_HEAP_LIMIT);
sendIntent.setPackage(directLaunchPackage);
try {
startActivity(sendIntent);
mHandled = true;
finish();
return;
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Unable to direct launch to " + directLaunchPackage, e);
}
}
final int messageId;
if (isUserInitiated) {
messageId = com.android.internal.R.string.dump_heap_ready_text;
} else if (isSystemProcess) {
messageId = com.android.internal.R.string.dump_heap_system_text;
} else {
messageId = com.android.internal.R.string.dump_heap_text;
}
mDialog = new AlertDialog.Builder(this, android.R.style.Theme_Material_Light_Dialog_Alert)
.setTitle(com.android.internal.R.string.dump_heap_title)
.setMessage(getString(messageId, procDisplayName,
DebugUtils.sizeValueToString(size, null)))
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
mHandled = true;
finish();
})
.setNeutralButton(R.string.delete, (dialog, which) -> {
mHandled = true;
Intent deleteIntent = new Intent(ACTION_DELETE_HEAP_DUMP);
deleteIntent.setClass(getApplicationContext(), HeapDumpReceiver.class);
deleteIntent.putExtra(KEY_URI, mDumpUri.toString());
sendBroadcast(deleteIntent);
finish();
})
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
mHandled = true;
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setPackage(null);
startActivity(Intent.createChooser(sendIntent,
getText(com.android.internal.R.string.dump_heap_title)));
finish();
})
.show();
}
@Override
protected void onStop() {
super.onStop();
if (!isChangingConfigurations()) {
if (!mHandled) {
Intent deleteIntent = new Intent(ACTION_DELETE_HEAP_DUMP);
deleteIntent.setClass(getApplicationContext(), HeapDumpReceiver.class);
deleteIntent.putExtra(KEY_URI, mDumpUri.toString());
sendBroadcast(deleteIntent);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mDialog != null) {
mDialog.dismiss();
}
}
}