public Debug.MemoryInfo dumpMemInfo( FileDescriptor fd, boolean checkin, boolean all, String[] args) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeFileDescriptor(fd); data.writeInt(checkin ? 1 : 0); data.writeInt(all ? 1 : 0); data.writeStringArray(args); mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0); reply.readException(); Debug.MemoryInfo info = new Debug.MemoryInfo(); info.readFromParcel(reply); data.recycle(); reply.recycle(); return info; }
/** * @param ctx 上下文环境 * @return 当前手机正在运行的进程的相关信息 */ public static List<ProcessInfo> getProcessInfo(Context ctx) { // 获取进程相关信息 List<ProcessInfo> processInfoList = new ArrayList<ProcessInfo>(); // 1,activityManager管理者对象和PackageManager管理者对象 ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); PackageManager pm = ctx.getPackageManager(); // 2,获取正在运行的进程的集合 List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses(); // 3,循环遍历上诉集合,获取进程相关信息(名称,包名,图标,使用内存大小,是否为系统进程(状态机)) for (RunningAppProcessInfo info : runningAppProcesses) { ProcessInfo processInfo = new ProcessInfo(); // 4,获取进程的名称 == 应用的包名 processInfo.packageName = info.processName; // 5,获取进程占用的内存大小(传递一个进程对应的pid数组) android.os.Debug.MemoryInfo[] processMemoryInfo = am.getProcessMemoryInfo(new int[] {info.pid}); // 6,返回数组中索引位置为0的对象,为当前进程的内存信息的对象 android.os.Debug.MemoryInfo memoryInfo = processMemoryInfo[0]; // 7,获取已使用的大小 processInfo.memSize = memoryInfo.getTotalPrivateDirty() * 1024; try { ApplicationInfo applicationInfo = pm.getApplicationInfo(processInfo.packageName, 0); // 8,获取应用的名称 processInfo.name = applicationInfo.loadLabel(pm).toString(); // 9,获取应用的图标 processInfo.icon = applicationInfo.loadIcon(pm); // 10,判断是否为系统进程 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM) { processInfo.isSystem = true; } else { processInfo.isSystem = false; } } catch (NameNotFoundException e) { // 需要处理 processInfo.name = info.processName; processInfo.icon = ctx.getResources().getDrawable(R.drawable.ic_launcher); processInfo.isSystem = true; e.printStackTrace(); } processInfoList.add(processInfo); } return processInfoList; }
public void getMemoryInfo(Debug.MemoryInfo outInfo) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); mRemote.transact(GET_MEMORY_INFO_TRANSACTION, data, reply, 0); reply.readException(); outInfo.readFromParcel(reply); data.recycle(); reply.recycle(); }
boolean updateSize(Context context, Debug.MemoryInfo mem, int curSeq) { mSize = ((long) mem.getTotalPss()) * 1024; if (mCurSeq == curSeq) { String sizeStr = Formatter.formatShortFileSize(context, mSize); if (!sizeStr.equals(mSizeStr)) { mSizeStr = sizeStr; // We update this on the second tick where we update just // the text in the current items, so no need to say we // changed here. return false; } } return false; }
/** * Get all running apps 如何判断多个进程是属于一个app? 1. 相同的前缀包名 返回的运行时应用列表, 按照内存占用量降序排序 * * @param ctx * @return */ public List<Map<String, Object>> getRunningApps(Context ctx) { // get all running app processes List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses(); if (runningAppProcesses == null) return null; // sort all running app processes Collections.sort( runningAppProcesses, new Comparator<RunningAppProcessInfo>() { @Override public int compare(RunningAppProcessInfo lhs, RunningAppProcessInfo rhs) { String lhsPkgName = lhs.processName.split(":")[0]; String rhsPkgName = rhs.processName.split(":")[0]; return lhsPkgName.compareToIgnoreCase(rhsPkgName); } }); Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); ResolveInfo resolveInfo = appHelper.getPm().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); String currentHomePackage = resolveInfo.activityInfo.packageName; IGNORE_PKGS.add(currentHomePackage); // remove all ignored packages Log.i(TAG, "before remove :" + runningAppProcesses.size()); ArrayList<RunningAppProcessInfo> toBeRemoved = new ArrayList<RunningAppProcessInfo>(); for (RunningAppProcessInfo runningProcessInfo : runningAppProcesses) { Log.i(TAG, "after sort:" + runningProcessInfo.processName); try { String appPkgname = runningProcessInfo.processName.split(":")[0]; if (IGNORE_PKGS.contains(appPkgname)) { toBeRemoved.add(runningProcessInfo); } } catch (Exception e) { e.printStackTrace(); Log.w(TAG, "exception raised while remove ignore list:" + e.toString()); } } runningAppProcesses.removeAll(toBeRemoved); Log.i( TAG, "removed :" + toBeRemoved.size() + " ignored packages, after remove size:" + runningAppProcesses.size()); Map<String, Map<String, Object>> runningApps = new HashMap<String, Map<String, Object>>(); // iterate the running app process list for (RunningAppProcessInfo runningProcessInfo : runningAppProcesses) { String[] pkgNameSections = runningProcessInfo.processName.split(":"); Log.i( TAG, "process name:" + runningProcessInfo.processName + ", pkgNameSections length:" + pkgNameSections.length); if (pkgNameSections.length == 0) { // TODO: process name is ""? continue; } String appPkgname = pkgNameSections[0]; String subProcessName = (pkgNameSections.length == 2) ? pkgNameSections[1] : null; Log.i(TAG, "appPkgname:" + appPkgname + ", subProcessName:" + subProcessName); // get application info from package name ApplicationInfo appInfo = appHelper.getApplicationInfo(appPkgname); if (appInfo == null) appInfo = appHelper.getApplicationInfo(runningProcessInfo.processName); // get app info by app package name Map<String, Object> appInfoMap = runningApps.get(appPkgname); if (appInfoMap == null) appInfoMap = new HashMap<String, Object>(); // put app package name if (!appInfoMap.containsKey(PKG_NAME)) { appInfoMap.put(PKG_NAME, appPkgname); } // put app uid if (!appInfoMap.containsKey(APP_UID)) { appInfoMap.put(APP_UID, runningProcessInfo.uid); } // put recommend flag if (!appInfoMap.containsKey(APP_RECOMMEND_CLEAN)) { appInfoMap.put(APP_RECOMMEND_CLEAN, !NOT_RECOMMAND_PKGS.contains(appPkgname)); } // only main process can get human readable name if (appInfo != null) { appInfoMap.put(APP_NAME, appInfo.loadLabel(appHelper.getPm()).toString()); } else if (!appInfoMap.containsKey(APP_NAME)) { appInfoMap.put(APP_NAME, appPkgname); } // get and put app icon if (appInfo != null) { appInfoMap.put(APP_ICON, appInfo.loadIcon(appHelper.getPm())); } else if (!appInfoMap.containsKey(APP_ICON)) { appInfoMap.put(APP_ICON, android.R.drawable.sym_def_app_icon); } // get memory size of app process, store mem info <Key(pid), Value(Debug.MemoryInfo)> SparseArray<Debug.MemoryInfo> memoryInfoArray = (SparseArray<Debug.MemoryInfo>) appInfoMap.get(APP_PROC_MEM); if (memoryInfoArray == null) memoryInfoArray = new SparseArray<Debug.MemoryInfo>(); Debug.MemoryInfo memInfo = getDebugMemoryInfos(new int[] {runningProcessInfo.pid})[0]; memoryInfoArray.put(runningProcessInfo.pid, memInfo); appInfoMap.put(APP_PROC_MEM, memoryInfoArray); // update total int totalPss = 0; if (appInfoMap.containsKey(APP_TOTAL_PSS)) totalPss = (Integer) appInfoMap.get(APP_TOTAL_PSS); totalPss += memInfo.getTotalPss(); appInfoMap.put(APP_TOTAL_PSS, totalPss); // add process in process array List<RunningAppProcessInfo> processes = (ArrayList<RunningAppProcessInfo>) appInfoMap.get(APP_PROCS); if (processes == null) processes = new ArrayList<RunningAppProcessInfo>(); processes.add(runningProcessInfo); appInfoMap.put(APP_PROCS, processes); runningApps.put(appPkgname, appInfoMap); } return sortMap(runningApps); }
@Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (mDragging) { if (mAnimationState == ANIMATION_STATE_STARTING) { mAnimationStartTime = SystemClock.uptimeMillis(); mAnimationState = ANIMATION_STATE_RUNNING; } if (mAnimationState == ANIMATION_STATE_RUNNING) { float normalized = (float) (SystemClock.uptimeMillis() - mAnimationStartTime) / mAnimationDuration; if (normalized >= 1.0f) { mAnimationState = ANIMATION_STATE_DONE; } normalized = Math.min(normalized, 1.0f); final float value = mAnimationFrom + (mAnimationTo - mAnimationFrom) * normalized; switch (mAnimationType) { case ANIMATION_TYPE_SCALE: if (mDrawModeBitmap && mDragBitmap != null) { final Bitmap dragBitmap = mDragBitmap; canvas.save(); canvas.translate( getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX, getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY); canvas.translate( (dragBitmap.getWidth() * (1.0f - value)) / 2, (dragBitmap.getHeight() * (1.0f - value)) / 2); canvas.scale(value, value); canvas.drawBitmap(dragBitmap, 0.0f, 0.0f, mDragPaint); canvas.restore(); } else { canvas.save(); canvas.translate( getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX, getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY); canvas.translate( (mDrawWidth * (1.0f - value)) / 2, (mDrawHeight * (1.0f - value)) / 2); canvas.drawRoundRect( new RectF(0, 0, mDrawWidth, mDrawHeight), 8.0f, 8.0f, mRectPaint); canvas.restore(); } break; } } else { // Draw actual icon being dragged if (mDrawModeBitmap && mDragBitmap != null) { canvas.drawBitmap( mDragBitmap, getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX, getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY, mDragPaint); } else { canvas.save(); canvas.translate( getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX, getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY); canvas.drawRoundRect(new RectF(0, 0, mDrawWidth, mDrawHeight), 8.0f, 8.0f, mRectPaint); canvas.restore(); } } } if (pids.length > 0 && AlmostNexusSettingsHelper.getDebugShowMemUsage(getContext())) { mRectPaint.setTextSize(debugTextSize); mRectPaint.setAntiAlias(true); mRectPaint.setColor(0xff000000); if (pids.length > 0) canvas.drawRect(0, 0, getWidth(), 70, mRectPaint); mRectPaint.setColor(0xffffffff); memoryInfoArray = activityManager.getProcessMemoryInfo(pids); for (Debug.MemoryInfo pidMemoryInfo : memoryInfoArray) { canvas.drawText( "getTotalPrivateDirty: " + pidMemoryInfo.getTotalPrivateDirty(), 0, debugTextSize, mRectPaint); canvas.drawText( "getTotalPss: " + pidMemoryInfo.getTotalPss(), 0, debugTextSize * 2, mRectPaint); canvas.drawText( "getTotalSharedDirty: " + pidMemoryInfo.getTotalSharedDirty(), 0, debugTextSize * 3, mRectPaint); } } }
@Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean finished = data.readInt() != 0; boolean userLeaving = data.readInt() != 0; int configChanges = data.readInt(); schedulePauseActivity(b, finished, userLeaving, configChanges); return true; } case SCHEDULE_STOP_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean show = data.readInt() != 0; int configChanges = data.readInt(); scheduleStopActivity(b, show, configChanges); return true; } case SCHEDULE_WINDOW_VISIBILITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean show = data.readInt() != 0; scheduleWindowVisibility(b, show); return true; } case SCHEDULE_SLEEPING_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean sleeping = data.readInt() != 0; scheduleSleeping(b, sleeping); return true; } case SCHEDULE_RESUME_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean isForward = data.readInt() != 0; scheduleResumeActivity(b, isForward); return true; } case SCHEDULE_SEND_RESULT_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR); scheduleSendResult(b, ri); return true; } case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); Intent intent = Intent.CREATOR.createFromParcel(data); IBinder b = data.readStrongBinder(); int ident = data.readInt(); ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data); Configuration curConfig = Configuration.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); Bundle state = data.readBundle(); List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR); List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); boolean notResumed = data.readInt() != 0; boolean isForward = data.readInt() != 0; String profileName = data.readString(); ParcelFileDescriptor profileFd = data.readInt() != 0 ? data.readFileDescriptor() : null; boolean autoStopProfiler = data.readInt() != 0; scheduleLaunchActivity( intent, b, ident, info, curConfig, compatInfo, state, ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler); return true; } case SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR); List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); int configChanges = data.readInt(); boolean notResumed = data.readInt() != 0; Configuration config = null; if (data.readInt() != 0) { config = Configuration.CREATOR.createFromParcel(data); } scheduleRelaunchActivity(b, ri, pi, configChanges, notResumed, config); return true; } case SCHEDULE_NEW_INTENT_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); IBinder b = data.readStrongBinder(); scheduleNewIntent(pi, b); return true; } case SCHEDULE_FINISH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean finishing = data.readInt() != 0; int configChanges = data.readInt(); scheduleDestroyActivity(b, finishing, configChanges); return true; } case SCHEDULE_RECEIVER_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); Intent intent = Intent.CREATOR.createFromParcel(data); ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); int resultCode = data.readInt(); String resultData = data.readString(); Bundle resultExtras = data.readBundle(); boolean sync = data.readInt() != 0; scheduleReceiver(intent, info, compatInfo, resultCode, resultData, resultExtras, sync); return true; } case SCHEDULE_CREATE_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); scheduleCreateService(token, info, compatInfo); return true; } case SCHEDULE_BIND_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); Intent intent = Intent.CREATOR.createFromParcel(data); boolean rebind = data.readInt() != 0; scheduleBindService(token, intent, rebind); return true; } case SCHEDULE_UNBIND_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); Intent intent = Intent.CREATOR.createFromParcel(data); scheduleUnbindService(token, intent); return true; } case SCHEDULE_SERVICE_ARGS_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); boolean taskRemoved = data.readInt() != 0; int startId = data.readInt(); int fl = data.readInt(); Intent args; if (data.readInt() != 0) { args = Intent.CREATOR.createFromParcel(data); } else { args = null; } scheduleServiceArgs(token, taskRemoved, startId, fl, args); return true; } case SCHEDULE_STOP_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); scheduleStopService(token); return true; } case BIND_APPLICATION_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); String packageName = data.readString(); ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data); List<ProviderInfo> providers = data.createTypedArrayList(ProviderInfo.CREATOR); ComponentName testName = (data.readInt() != 0) ? new ComponentName(data) : null; String profileName = data.readString(); ParcelFileDescriptor profileFd = data.readInt() != 0 ? data.readFileDescriptor() : null; boolean autoStopProfiler = data.readInt() != 0; Bundle testArgs = data.readBundle(); IBinder binder = data.readStrongBinder(); IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder); int testMode = data.readInt(); boolean restrictedBackupMode = (data.readInt() != 0); boolean persistent = (data.readInt() != 0); Configuration config = Configuration.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); HashMap<String, IBinder> services = data.readHashMap(null); Bundle coreSettings = data.readBundle(); bindApplication( packageName, info, providers, testName, profileName, profileFd, autoStopProfiler, testArgs, testWatcher, testMode, restrictedBackupMode, persistent, config, compatInfo, services, coreSettings); return true; } case SCHEDULE_EXIT_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); scheduleExit(); return true; } case SCHEDULE_SUICIDE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); scheduleSuicide(); return true; } case REQUEST_THUMBNAIL_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); requestThumbnail(b); return true; } case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); Configuration config = Configuration.CREATOR.createFromParcel(data); scheduleConfigurationChanged(config); return true; } case UPDATE_TIME_ZONE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); updateTimeZone(); return true; } case CLEAR_DNS_CACHE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); clearDnsCache(); return true; } case SET_HTTP_PROXY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); final String proxy = data.readString(); final String port = data.readString(); final String exclList = data.readString(); setHttpProxy(proxy, port, exclList); return true; } case PROCESS_IN_BACKGROUND_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); processInBackground(); return true; } case DUMP_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); final IBinder service = data.readStrongBinder(); final String[] args = data.readStringArray(); if (fd != null) { dumpService(fd.getFileDescriptor(), service, args); try { fd.close(); } catch (IOException e) { } } return true; } case SCHEDULE_REGISTERED_RECEIVER_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IIntentReceiver receiver = IIntentReceiver.Stub.asInterface(data.readStrongBinder()); Intent intent = Intent.CREATOR.createFromParcel(data); int resultCode = data.readInt(); String dataStr = data.readString(); Bundle extras = data.readBundle(); boolean ordered = data.readInt() != 0; boolean sticky = data.readInt() != 0; scheduleRegisteredReceiver( receiver, intent, resultCode, dataStr, extras, ordered, sticky); return true; } case SCHEDULE_LOW_MEMORY_TRANSACTION: { scheduleLowMemory(); return true; } case SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); scheduleActivityConfigurationChanged(b); return true; } case PROFILER_CONTROL_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); boolean start = data.readInt() != 0; int profileType = data.readInt(); String path = data.readString(); ParcelFileDescriptor fd = data.readInt() != 0 ? data.readFileDescriptor() : null; profilerControl(start, path, fd, profileType); return true; } case SET_SCHEDULING_GROUP_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); int group = data.readInt(); setSchedulingGroup(group); return true; } case SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); int backupMode = data.readInt(); scheduleCreateBackupAgent(appInfo, compatInfo, backupMode); return true; } case SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); scheduleDestroyBackupAgent(appInfo, compatInfo); return true; } case GET_MEMORY_INFO_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); Debug.MemoryInfo mi = new Debug.MemoryInfo(); getMemoryInfo(mi); reply.writeNoException(); mi.writeToParcel(reply, 0); return true; } case DISPATCH_PACKAGE_BROADCAST_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); int cmd = data.readInt(); String[] packages = data.readStringArray(); dispatchPackageBroadcast(cmd, packages); return true; } case SCHEDULE_CRASH_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); String msg = data.readString(); scheduleCrash(msg); return true; } case DUMP_HEAP_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); boolean managed = data.readInt() != 0; String path = data.readString(); ParcelFileDescriptor fd = data.readInt() != 0 ? data.readFileDescriptor() : null; dumpHeap(managed, path, fd); return true; } case DUMP_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); final IBinder activity = data.readStrongBinder(); final String prefix = data.readString(); final String[] args = data.readStringArray(); if (fd != null) { dumpActivity(fd.getFileDescriptor(), activity, prefix, args); try { fd.close(); } catch (IOException e) { } } return true; } case SET_CORE_SETTINGS_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); Bundle settings = data.readBundle(); setCoreSettings(settings); return true; } case UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); String pkg = data.readString(); CompatibilityInfo compat = CompatibilityInfo.CREATOR.createFromParcel(data); updatePackageCompatibilityInfo(pkg, compat); return true; } case SCHEDULE_TRIM_MEMORY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); int level = data.readInt(); scheduleTrimMemory(level); return true; } case DUMP_MEM_INFO_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); boolean checkin = data.readInt() != 0; boolean all = data.readInt() != 0; String[] args = data.readStringArray(); Debug.MemoryInfo mi = null; if (fd != null) { try { mi = dumpMemInfo(fd.getFileDescriptor(), checkin, all, args); } finally { try { fd.close(); } catch (IOException e) { // swallowed, not propagated back to the caller } } } reply.writeNoException(); mi.writeToParcel(reply, 0); return true; } case DUMP_GFX_INFO_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); String[] args = data.readStringArray(); if (fd != null) { try { dumpGfxInfo(fd.getFileDescriptor(), args); } finally { try { fd.close(); } catch (IOException e) { // swallowed, not propagated back to the caller } } } reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); }