Loading core/java/android/app/ActivityManagerNative.java +21 −0 Original line number Diff line number Diff line Loading @@ -2842,6 +2842,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } case IS_APP_FOREGROUND_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); final int userHandle = data.readInt(); final boolean isForeground = isAppForeground(userHandle); reply.writeNoException(); reply.writeInt(isForeground ? 1 : 0); return true; } } return super.onTransact(code, data, reply, flags); Loading Loading @@ -6639,5 +6647,18 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } @Override public boolean isAppForeground(int uid) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(uid); mRemote.transact(IS_APP_FOREGROUND_TRANSACTION, data, reply, 0); final boolean isForeground = reply.readInt() == 1 ? true : false; data.recycle(); reply.recycle(); return isForeground; }; private IBinder mRemote; } core/java/android/app/IActivityManager.java +3 −0 Original line number Diff line number Diff line Loading @@ -589,6 +589,8 @@ public interface IActivityManager extends IInterface { public void setVrMode(IBinder token, boolean enabled) throws RemoteException; public boolean isAppForeground(int uid) throws RemoteException; /* * Private non-Binder interfaces */ Loading Loading @@ -960,4 +962,5 @@ public interface IActivityManager extends IInterface { int SET_VR_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 359; int GET_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 360; int CLEAR_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 361; int IS_APP_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 362; } services/backup/java/com/android/server/backup/BackupManagerService.java +65 −23 Original line number Diff line number Diff line Loading @@ -239,6 +239,11 @@ public class BackupManagerService { // How long between attempts to perform a full-data backup of any given app static final long MIN_FULL_BACKUP_INTERVAL = 1000 * 60 * 60 * 24; // one day // If an app is busy when we want to do a full-data backup, how long to defer the retry. // This is fuzzed, so there are two parameters; backoff_min + Rand[0, backoff_fuzz) static final long BUSY_BACKOFF_MIN_MILLIS = 1000 * 60 * 60; // one hour static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2; // two hours Context mContext; private PackageManager mPackageManager; IPackageManager mPackageManagerBinder; Loading Loading @@ -4496,10 +4501,14 @@ public class BackupManagerService { return false; } // At this point we know that we have work to do, just not right now. Any // exit without actually running backups will also require that we // At this point we know that we have work to do, but possibly not right now. // Any exit without actually running backups will also require that we // reschedule the job. boolean runBackup = true; boolean headBusy; do { headBusy = false; if (!fullBackupAllowable(getTransport(mCurrentTransport))) { if (MORE_DEBUG) { Loading @@ -4523,8 +4532,41 @@ public class BackupManagerService { } // Wait until the next app in the queue falls due for a full data backup latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun; break; // we know we aren't doing work yet, so bail. } try { PackageInfo appInfo = mPackageManager.getPackageInfo(entry.packageName, 0); headBusy = mActivityManager.isAppForeground(appInfo.applicationInfo.uid); if (headBusy) { final long nextEligible = System.currentTimeMillis() + BUSY_BACKOFF_MIN_MILLIS + mTokenGenerator.nextInt(BUSY_BACKOFF_FUZZ); if (DEBUG_SCHEDULING) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Slog.i(TAG, "Full backup time but " + entry.packageName + " is busy; deferring to " + sdf.format(new Date(nextEligible))); } // This relocates the app's entry from the head of the queue to // its order-appropriate position further down, so upon looping // a new candidate will be considered at the head. enqueueFullBackup(entry.packageName, nextEligible - MIN_FULL_BACKUP_INTERVAL); } } catch (NameNotFoundException nnf) { // So, we think we want to back this up, but it turns out the package // in question is no longer installed. We want to drop it from the // queue entirely and move on, but if there's nothing else in the queue // we should bail entirely. headBusy cannot have been set to true yet. runBackup = (mFullBackupQueue.size() > 1); } catch (RemoteException e) { // Cannot happen; the Activity Manager is in the same process } } } while (headBusy); if (!runBackup) { if (DEBUG_SCHEDULING) { Loading @@ -4539,7 +4581,7 @@ public class BackupManagerService { return false; } // Okay, the top thing is runnable now. Pop it off and get going. // Okay, the top thing is ready for backup now. Do it. mFullBackupQueue.remove(0); CountDownLatch latch = new CountDownLatch(1); String[] pkg = new String[] {entry.packageName}; Loading services/core/java/com/android/server/am/ActivityManagerService.java +12 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.am; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.AssistUtils; Loading Loading @@ -240,6 +239,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import dalvik.system.VMRuntime; import libcore.io.IoUtils; import libcore.util.EmptyArray; Loading Loading @@ -7255,6 +7255,17 @@ public final class ActivityManagerService extends ActivityManagerNative } } @Override public boolean isAppForeground(int uid) throws RemoteException { synchronized (this) { UidRecord uidRec = mActiveUids.get(uid); if (uidRec == null || uidRec.idle) { return false; } return uidRec.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; } } @Override public boolean inMultiWindowMode(IBinder token) { final long origId = Binder.clearCallingIdentity(); Loading Loading
core/java/android/app/ActivityManagerNative.java +21 −0 Original line number Diff line number Diff line Loading @@ -2842,6 +2842,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } case IS_APP_FOREGROUND_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); final int userHandle = data.readInt(); final boolean isForeground = isAppForeground(userHandle); reply.writeNoException(); reply.writeInt(isForeground ? 1 : 0); return true; } } return super.onTransact(code, data, reply, flags); Loading Loading @@ -6639,5 +6647,18 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } @Override public boolean isAppForeground(int uid) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(uid); mRemote.transact(IS_APP_FOREGROUND_TRANSACTION, data, reply, 0); final boolean isForeground = reply.readInt() == 1 ? true : false; data.recycle(); reply.recycle(); return isForeground; }; private IBinder mRemote; }
core/java/android/app/IActivityManager.java +3 −0 Original line number Diff line number Diff line Loading @@ -589,6 +589,8 @@ public interface IActivityManager extends IInterface { public void setVrMode(IBinder token, boolean enabled) throws RemoteException; public boolean isAppForeground(int uid) throws RemoteException; /* * Private non-Binder interfaces */ Loading Loading @@ -960,4 +962,5 @@ public interface IActivityManager extends IInterface { int SET_VR_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 359; int GET_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 360; int CLEAR_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 361; int IS_APP_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 362; }
services/backup/java/com/android/server/backup/BackupManagerService.java +65 −23 Original line number Diff line number Diff line Loading @@ -239,6 +239,11 @@ public class BackupManagerService { // How long between attempts to perform a full-data backup of any given app static final long MIN_FULL_BACKUP_INTERVAL = 1000 * 60 * 60 * 24; // one day // If an app is busy when we want to do a full-data backup, how long to defer the retry. // This is fuzzed, so there are two parameters; backoff_min + Rand[0, backoff_fuzz) static final long BUSY_BACKOFF_MIN_MILLIS = 1000 * 60 * 60; // one hour static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2; // two hours Context mContext; private PackageManager mPackageManager; IPackageManager mPackageManagerBinder; Loading Loading @@ -4496,10 +4501,14 @@ public class BackupManagerService { return false; } // At this point we know that we have work to do, just not right now. Any // exit without actually running backups will also require that we // At this point we know that we have work to do, but possibly not right now. // Any exit without actually running backups will also require that we // reschedule the job. boolean runBackup = true; boolean headBusy; do { headBusy = false; if (!fullBackupAllowable(getTransport(mCurrentTransport))) { if (MORE_DEBUG) { Loading @@ -4523,8 +4532,41 @@ public class BackupManagerService { } // Wait until the next app in the queue falls due for a full data backup latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun; break; // we know we aren't doing work yet, so bail. } try { PackageInfo appInfo = mPackageManager.getPackageInfo(entry.packageName, 0); headBusy = mActivityManager.isAppForeground(appInfo.applicationInfo.uid); if (headBusy) { final long nextEligible = System.currentTimeMillis() + BUSY_BACKOFF_MIN_MILLIS + mTokenGenerator.nextInt(BUSY_BACKOFF_FUZZ); if (DEBUG_SCHEDULING) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Slog.i(TAG, "Full backup time but " + entry.packageName + " is busy; deferring to " + sdf.format(new Date(nextEligible))); } // This relocates the app's entry from the head of the queue to // its order-appropriate position further down, so upon looping // a new candidate will be considered at the head. enqueueFullBackup(entry.packageName, nextEligible - MIN_FULL_BACKUP_INTERVAL); } } catch (NameNotFoundException nnf) { // So, we think we want to back this up, but it turns out the package // in question is no longer installed. We want to drop it from the // queue entirely and move on, but if there's nothing else in the queue // we should bail entirely. headBusy cannot have been set to true yet. runBackup = (mFullBackupQueue.size() > 1); } catch (RemoteException e) { // Cannot happen; the Activity Manager is in the same process } } } while (headBusy); if (!runBackup) { if (DEBUG_SCHEDULING) { Loading @@ -4539,7 +4581,7 @@ public class BackupManagerService { return false; } // Okay, the top thing is runnable now. Pop it off and get going. // Okay, the top thing is ready for backup now. Do it. mFullBackupQueue.remove(0); CountDownLatch latch = new CountDownLatch(1); String[] pkg = new String[] {entry.packageName}; Loading
services/core/java/com/android/server/am/ActivityManagerService.java +12 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.am; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.AssistUtils; Loading Loading @@ -240,6 +239,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import dalvik.system.VMRuntime; import libcore.io.IoUtils; import libcore.util.EmptyArray; Loading Loading @@ -7255,6 +7255,17 @@ public final class ActivityManagerService extends ActivityManagerNative } } @Override public boolean isAppForeground(int uid) throws RemoteException { synchronized (this) { UidRecord uidRec = mActiveUids.get(uid); if (uidRec == null || uidRec.idle) { return false; } return uidRec.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; } } @Override public boolean inMultiWindowMode(IBinder token) { final long origId = Binder.clearCallingIdentity(); Loading