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