package com.eolwral.osmonitor.util; import java.util.HashMap; import java.util.LinkedList; import java.util.concurrent.Semaphore; import com.eolwral.osmonitor.R; import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Debug.MemoryInfo; import android.util.DisplayMetrics; import android.view.WindowManager; /** * help to gather the information of process and cache data * * @author eolwral */ public class ProcessUtil extends Thread { private static ProcessUtil singletone = null; private static final Rect rect = new Rect(); private static final Canvas canvas = new Canvas(); private PackageManager packageMgr = null; private Resources resourceMgr = null; private ActivityManager activityMgr = null; private Drawable commonIcon = null; private boolean useDetail = true; private int iconSize = 60; private class CacheItem { public String name; public Drawable icon; } // cache private final HashMap<String, CacheItem> cacheStorage = new HashMap<String, CacheItem>(); // work queue for background thread private final Semaphore queryQueueLock = new Semaphore(1, true); private final LinkedList<QueueJob> queryQueue = new LinkedList<QueueJob>(); // DPI public static final int DENSITY_LOW = 120; public static final int DENSITY_MEDIUM = 160; public static final int DENSITY_HIGH = 240; public static final int DENSITY_XHIGH = 320; public static final int DENSITY_XXHIGH = 480; public static ProcessUtil getInstance(Context context, boolean detail) { if (singletone != null) return singletone; singletone = new ProcessUtil(); singletone.packageMgr = context.getPackageManager(); singletone.resourceMgr = context.getResources(); singletone.activityMgr = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); DisplayMetrics metrics = new DisplayMetrics(); WindowManager wmanager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); wmanager.getDefaultDisplay().getMetrics(metrics); switch (metrics.densityDpi) { case DENSITY_LOW: singletone.iconSize = 15; break; case DENSITY_MEDIUM: singletone.iconSize = 20; break; case 213: // DENSITY_TV singletone.iconSize = 30; break; case DENSITY_HIGH: singletone.iconSize = 40; break; case 400: // DENSITY_400 singletone.iconSize = 45; break; case DENSITY_XHIGH: singletone.iconSize = 50; break; case DENSITY_XXHIGH: singletone.iconSize = 65; break; case 640: // DENSITY_XXXHIGH singletone.iconSize = 80; break; } singletone.useDetail = detail; if (singletone.useDetail == true) singletone.commonIcon = resizeImage(singletone.resourceMgr.getDrawable(R.drawable.ic_process_system), singletone.iconSize); singletone.start(); return singletone; } public void doCacheInfo(int uid, String owner, String process) { // add a job into work queue try { queryQueueLock.acquire(); } catch (InterruptedException e) { return; } queryQueue.add(new QueueJob(uid, owner, process)); queryQueueLock.release(); // create a skeleton object CacheItem skeletonItem = new CacheItem(); skeletonItem.name = process; skeletonItem.icon = commonIcon; cacheStorage.put(process, skeletonItem); return; } /** * a class for queued job */ private class QueueJob { public int uid; public String owner; public String process; public QueueJob(int uid, String owner, String process) { this.uid = uid; this.owner = owner; this.process = process; } } @Override public void run() { while (true) { if (getCacheInfo()) continue; try { sleep(500); } catch (InterruptedException e) { } } } /** * get information for process * * @return true == success, false == failed */ public boolean getCacheInfo() { if (queryQueue.isEmpty()) return false; try { queryQueueLock.acquire(); } catch (InterruptedException e) { return false; } QueueJob processJob = queryQueue.remove(); queryQueueLock.release(); PackageInfo curPackageInfo = null; String curPackageName = null; if (processJob.process.contains(":")) curPackageName = processJob.process.substring(0, processJob.process.indexOf(":")); else curPackageName = processJob.process; // for system user if (processJob.owner.contains("system") && processJob.process.contains("system") && !processJob.process.contains(".") && !processJob.process.contains("osmcore")) curPackageName = "android"; try { curPackageInfo = packageMgr.getPackageInfo(curPackageName, 0); } catch (NameNotFoundException e) { } if (curPackageInfo == null && processJob.uid > 0) { String[] subPackageName = packageMgr.getPackagesForUid(processJob.uid); if (subPackageName != null) { for (int PackagePtr = 0; PackagePtr < subPackageName.length; PackagePtr++) { if (subPackageName[PackagePtr] == null) continue; try { curPackageInfo = packageMgr.getPackageInfo(subPackageName[PackagePtr], 0); PackagePtr = subPackageName.length; } catch (NameNotFoundException e) { } } } } CacheItem processItem = new CacheItem(); if (curPackageInfo != null) { processItem.name = curPackageInfo.applicationInfo.loadLabel(packageMgr).toString(); if (useDetail == true) processItem.icon = resizeImage(curPackageInfo.applicationInfo.loadIcon(packageMgr), iconSize); } else { processItem.name = curPackageName; processItem.icon = commonIcon; } cacheStorage.put(processJob.process, processItem); return true; } /** * resize icon to the specific size * * @param icon * input image * @param size * icon size * @return resized image */ private static Drawable resizeImage(Drawable icon, int iconSize) { // create a new bitmap Bitmap bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); // reuse canvas and rect canvas.setBitmap(bitmap); icon.setBounds(0, 0, iconSize, iconSize); icon.draw(canvas); icon.setBounds(rect); // use try-catch to avoid crash // for Android 2.3.3 try { canvas.setBitmap(null); } catch (Exception e) {} return new BitmapDrawable(singletone.resourceMgr, bitmap); } /** * get the name of process * * @param process * the name of process * @return process name */ public String getPackageName(String process) { CacheItem Process = cacheStorage.get(process); if (Process != null) return Process.name; return null; } /** * get the icon of process * * @param process * the name of process * @return icon */ public Drawable getPackageIcon(String process) { CacheItem Process = cacheStorage.get(process); if (Process != null) return cacheStorage.get(process).icon; return null; } /** * get the default icon of process * * @return icon */ public Drawable getDefaultIcon() { return commonIcon; } /** * check process has been processed * * @param process * the name of process * @return true == cached, false == none */ public boolean checkPackageInformation(String process) { CacheItem Process = cacheStorage.get(process); if (Process == null) return false; return true; } /** * get private memory * * @param pid * the process id of process * @return private memory value */ public MemoryInfo getMemoryInfo(int pid) { int processPID[] = new int[1]; processPID[0] = pid; MemoryInfo[] memInfo = activityMgr.getProcessMemoryInfo(processPID); return memInfo[0]; } }