ForegroundUtils.java revision da772582c17e3f5ffe36e4cab3e1ede3cba32060
138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri/*
238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * Copyright (C) 2014 The Android Open Source Project
338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri *
438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * Licensed under the Apache License, Version 2.0 (the "License");
538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * you may not use this file except in compliance with the License.
638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * You may obtain a copy of the License at
738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri *
838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri *      http://www.apache.org/licenses/LICENSE-2.0
938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri *
1038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * Unless required by applicable law or agreed to in writing, software
1138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * distributed under the License is distributed on an "AS IS" BASIS,
1238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * See the License for the specific language governing permissions and
1438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri * limitations under the License.
1538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri */
1638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieripackage com.android.nfc;
1738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
1838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport java.util.ArrayList;
1938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport java.util.List;
2038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
2138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport android.app.ActivityManagerNative;
2238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport android.app.IActivityManager;
2338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport android.app.IProcessObserver;
2438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport android.os.RemoteException;
2538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport android.util.Log;
2638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieriimport android.util.SparseArray;
2738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
2838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieripublic class ForegroundUtils extends IProcessObserver.Stub {
2938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private final String TAG = "ForegroundUtils";
3038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private final IActivityManager mIActivityManager;
3138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
3238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private final Object mLock = new Object();
3338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private final SparseArray<Boolean> mForegroundUids = new SparseArray<Boolean>(1);
3438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private final SparseArray<List<Callback>> mBackgroundCallbacks =
3538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            new SparseArray<List<Callback>>();
3638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
3738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private static class Singleton {
3838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        private static final ForegroundUtils INSTANCE = new ForegroundUtils();
3938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
4038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
4138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    private ForegroundUtils() {
4238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        mIActivityManager = ActivityManagerNative.getDefault();
4338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        try {
4438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            mIActivityManager.registerProcessObserver(this);
4538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        } catch (RemoteException e) {
4638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            // Should not happen!
4738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            Log.e(TAG, "ForegroundUtils: could not get IActivityManager");
4838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        }
4938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
5038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
5138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public interface Callback {
5238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        void onUidToBackground(int uid);
5338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
5438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
5538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public static ForegroundUtils getInstance() {
5638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        return Singleton.INSTANCE;
5738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
5838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
5938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    /**
6038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * Checks whether the specified UID has any activities running in the foreground,
61f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri     * and if it does, registers a callback for when that UID no longer has any foreground
6238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * activities. This is done atomically, so callers can be ensured that they will
6338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * get a callback if this method returns true.
64f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri     *
6538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * @param callback Callback to be called
6638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * @param uid The UID to be checked
6738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * @return true when the UID has an Activity in the foreground and the callback
6838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * , false otherwise
6938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     */
7038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public boolean registerUidToBackgroundCallback(Callback callback, int uid) {
71f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        synchronized (mLock) {
7238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            if (!isInForegroundLocked(uid)) {
7338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri                return false;
7438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            }
7538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            // This uid is in the foreground; register callback for when it moves
7638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            // into the background.
7738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            List<Callback> callbacks = mBackgroundCallbacks.get(uid);
7838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            if (callbacks == null) {
7938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri                callbacks = new ArrayList<Callback>();
8038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri                mBackgroundCallbacks.put(uid, callbacks);
81f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri            }
82f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri            callbacks.add(callback);
8338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            return true;
8438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        }
8538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
8638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
8738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    /**
88f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri     * @param uid The UID to be checked
8938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     * @return whether the UID has any activities running in the foreground
9038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri     */
9138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public boolean isInForeground(int uid) {
9238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        synchronized (mLock) {
9338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            return isInForegroundLocked(uid);
9438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        }
9538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
9638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
97f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    boolean isInForegroundLocked(int uid) {
98f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        Boolean inForeground = mForegroundUids.get(uid);
99f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        return inForeground != null ? inForeground.booleanValue() : false;
100f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    }
101f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri
102f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    void handleUidToBackground(int uid) {
103f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        ArrayList<Callback> pendingCallbacks = null;
104f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        synchronized (mLock) {
105f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri            List<Callback> callbacks = mBackgroundCallbacks.get(uid);
106f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri            if (callbacks != null) {
107f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri                pendingCallbacks = new ArrayList<Callback>(callbacks);
108f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri                // Only call them once
109f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri                mBackgroundCallbacks.remove(uid);
110f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri            }
111f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        }
112f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        // Release lock for callbacks
113f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        if (pendingCallbacks != null) {
114f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri            for (Callback callback : pendingCallbacks) {
115f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri                callback.onUidToBackground(uid);
11638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            }
11738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        }
11838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    }
11938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
12038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    @Override
12138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public void onForegroundActivitiesChanged(int pid, int uid,
12238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            boolean foregroundActivities) throws RemoteException {
12338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        synchronized (mLock) {
12438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            mForegroundUids.put(uid, foregroundActivities);
12538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        }
12638da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        if (!foregroundActivities) {
12738da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            handleUidToBackground(uid);
12838da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        }
129f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    }
13038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
131f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri
132f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    @Override
13338da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public void onProcessDied(int pid, int uid) throws RemoteException {
13438da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri        synchronized (mLock) {
13538da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            mForegroundUids.remove(uid);
136f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        }
137f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        handleUidToBackground(uid);
138f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    }
13938da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri
14038da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    @Override
14138da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri    public void onProcessStateChanged(int pid, int uid, int procState)
14238da5c9cb636387539daaf5688c2a3badee32447Luca Barbieri            throws RemoteException {
143f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri        // Don't care
144f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri    }
145f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri}
146f976cd0c9ead6a5e63146c11823770176c149a12Luca Barbieri