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 android.util.SparseIntArray;
26fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
27fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackbornimport java.util.List;
28fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
29fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn/**
30fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * Helper for monitoring the current importance of applications.
31fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * @hide
32fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn */
33fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackbornpublic class AppImportanceMonitor {
34fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    final Context mContext;
35fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
36fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    final SparseArray<AppEntry> mApps = new SparseArray<>();
37fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
38fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    static class AppEntry {
39fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        final int uid;
40fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        final SparseArray<Integer> procs = new SparseArray<>(1);
41fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
42fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
43fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        AppEntry(int _uid) {
44fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            uid = _uid;
45fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
46fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    }
47fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
48fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
49fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        @Override
50fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
51fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
52fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
53fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        @Override
54fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        public void onProcessStateChanged(int pid, int uid, int procState) {
55fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            synchronized (mApps) {
56fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                updateImportanceLocked(pid, uid,
57fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                        ActivityManager.RunningAppProcessInfo.procStateToImportance(procState),
58fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                        true);
59fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
60fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
61fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
62fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        @Override
63fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        public void onProcessDied(int pid, int uid) {
64fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            synchronized (mApps) {
65fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                updateImportanceLocked(pid, uid,
66fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                        ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, true);
67fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
68fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
69fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    };
70fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
71fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    static final int MSG_UPDATE = 1;
72fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
73fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    final Handler mHandler;
74fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
75fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    public AppImportanceMonitor(Context context, Looper looper) {
76fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        mContext = context;
77fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        mHandler = new Handler(looper) {
78fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            @Override
79fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            public void handleMessage(Message msg) {
80fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                switch (msg.what) {
81fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                    case MSG_UPDATE:
82fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                        onImportanceChanged(msg.arg1, msg.arg2&0xffff, msg.arg2>>16);
83fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                        break;
84fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                    default:
85fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                        super.handleMessage(msg);
86fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                }
87fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
88fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        };
89fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
90fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        try {
91fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            ActivityManagerNative.getDefault().registerProcessObserver(mProcessObserver);
92fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        } catch (RemoteException e) {
93fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
94fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses();
95fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        if (apps != null) {
96fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            for (int i=0; i<apps.size(); i++) {
97fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                ActivityManager.RunningAppProcessInfo app = apps.get(i);
98fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                updateImportanceLocked(app.uid, app.pid, app.importance, false);
99fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
100fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
101fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    }
102fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
103fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    public int getImportance(int uid) {
104fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        AppEntry ent = mApps.get(uid);
105fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        if (ent == null) {
106fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
107fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
108fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        return ent.importance;
109fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    }
110fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
111fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    /**
112fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn     * Report when an app's importance changed. Called on looper given to constructor.
113fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn     */
114fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    public void onImportanceChanged(int uid, int importance, int oldImportance) {
115fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    }
116fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
117fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    void updateImportanceLocked(int uid, int pid, int importance, boolean repChange) {
118fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        AppEntry ent = mApps.get(uid);
119fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        if (ent == null) {
120fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            ent = new AppEntry(uid);
121fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            mApps.put(uid, ent);
122fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
123fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        if (importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
124fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            ent.procs.remove(pid);
125fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        } else {
126fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            ent.procs.put(pid, importance);
127fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
128fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        updateImportanceLocked(ent, repChange);
129fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    }
130fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn
131fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    void updateImportanceLocked(AppEntry ent, boolean repChange) {
132fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        int appImp = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
133fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        for (int i=0; i<ent.procs.size(); i++) {
134fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            int procImp = ent.procs.valueAt(i);
135fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            if (procImp < appImp) {
136fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                appImp = procImp;
137fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
138fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
139fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        if (appImp != ent.importance) {
140fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            int impCode = appImp | (ent.importance<<16);
141fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            ent.importance = appImp;
142fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            if (appImp >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
143fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                mApps.remove(ent.uid);
144fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
145fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            if (repChange) {
146fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn                mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget();
147fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn            }
148fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn        }
149fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn    }
150fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn}
151