Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.app;
     18 
     19 import android.content.Context;
     20 import android.os.Handler;
     21 import android.os.Looper;
     22 import android.os.Message;
     23 import android.os.RemoteException;
     24 import android.util.SparseArray;
     25 import java.util.List;
     26 
     27 /**
     28  * Helper for monitoring the current importance of applications.
     29  * @hide
     30  */
     31 public class AppImportanceMonitor {
     32     final Context mContext;
     33 
     34     final SparseArray<AppEntry> mApps = new SparseArray<>();
     35 
     36     static class AppEntry {
     37         final int uid;
     38         final SparseArray<Integer> procs = new SparseArray<>(1);
     39         int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
     40 
     41         AppEntry(int _uid) {
     42             uid = _uid;
     43         }
     44     }
     45 
     46     final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
     47         @Override
     48         public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
     49         }
     50 
     51         @Override
     52         public void onProcessStateChanged(int pid, int uid, int procState) {
     53             synchronized (mApps) {
     54                 updateImportanceLocked(pid, uid,
     55                         ActivityManager.RunningAppProcessInfo.procStateToImportance(procState),
     56                         true);
     57             }
     58         }
     59 
     60         @Override
     61         public void onProcessDied(int pid, int uid) {
     62             synchronized (mApps) {
     63                 updateImportanceLocked(pid, uid,
     64                         ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, true);
     65             }
     66         }
     67     };
     68 
     69     static final int MSG_UPDATE = 1;
     70 
     71     final Handler mHandler;
     72 
     73     public AppImportanceMonitor(Context context, Looper looper) {
     74         mContext = context;
     75         mHandler = new Handler(looper) {
     76             @Override
     77             public void handleMessage(Message msg) {
     78                 switch (msg.what) {
     79                     case MSG_UPDATE:
     80                         onImportanceChanged(msg.arg1, msg.arg2&0xffff, msg.arg2>>16);
     81                         break;
     82                     default:
     83                         super.handleMessage(msg);
     84                 }
     85             }
     86         };
     87         ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
     88         try {
     89             ActivityManagerNative.getDefault().registerProcessObserver(mProcessObserver);
     90         } catch (RemoteException e) {
     91         }
     92         List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses();
     93         if (apps != null) {
     94             for (int i=0; i<apps.size(); i++) {
     95                 ActivityManager.RunningAppProcessInfo app = apps.get(i);
     96                 updateImportanceLocked(app.uid, app.pid, app.importance, false);
     97             }
     98         }
     99     }
    100 
    101     public int getImportance(int uid) {
    102         AppEntry ent = mApps.get(uid);
    103         if (ent == null) {
    104             return ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
    105         }
    106         return ent.importance;
    107     }
    108 
    109     /**
    110      * Report when an app's importance changed. Called on looper given to constructor.
    111      */
    112     public void onImportanceChanged(int uid, int importance, int oldImportance) {
    113     }
    114 
    115     void updateImportanceLocked(int uid, int pid, int importance, boolean repChange) {
    116         AppEntry ent = mApps.get(uid);
    117         if (ent == null) {
    118             ent = new AppEntry(uid);
    119             mApps.put(uid, ent);
    120         }
    121         if (importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
    122             ent.procs.remove(pid);
    123         } else {
    124             ent.procs.put(pid, importance);
    125         }
    126         updateImportanceLocked(ent, repChange);
    127     }
    128 
    129     void updateImportanceLocked(AppEntry ent, boolean repChange) {
    130         int appImp = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
    131         for (int i=0; i<ent.procs.size(); i++) {
    132             int procImp = ent.procs.valueAt(i);
    133             if (procImp < appImp) {
    134                 appImp = procImp;
    135             }
    136         }
    137         if (appImp != ent.importance) {
    138             int impCode = appImp | (ent.importance<<16);
    139             ent.importance = appImp;
    140             if (appImp >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
    141                 mApps.remove(ent.uid);
    142             }
    143             if (repChange) {
    144                 mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget();
    145             }
    146         }
    147     }
    148 }
    149