Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95fc68f2 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue where apps could prevent the user from going home.

Now we have a 5-second time after home is pressed, during which
only the home app (and the status bar) can switch to another app.
After that time, any start activity requests that occurred will
be executed, to allow things like alarms to be displayed.  Also
if during that time the user launches another app, the pending
starts will be executed without resuming their activities and
the one they started placed at the top and executed.
parent ee748d37
Loading
Loading
Loading
Loading
+25 −15
Original line number Diff line number Diff line
@@ -194,18 +194,17 @@ public class Am {
        if (intent != null) {
            System.out.println("Starting: " + intent);
            try {
                intent.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                // XXX should do something to determine the MIME type.
                int res = mAm.startActivity(null, intent, intent.getType(),
                        null, 0, null, null, 0, false, mDebugOption);
                switch (res) {
                    case IActivityManager.START_SUCCESS:
                        break;
                    case IActivityManager.START_CLASS_NOT_FOUND:
                        System.err.println("Error type 3");
                        System.err.println("Error: Activity class " +
                                intent.getComponent().toShortString()
                                + " does not exist.");
                    case IActivityManager.START_SWITCHES_CANCELED:
                        System.err.println(
                                "Warning: Activity not started because the "
                                + " current activity is being kept for the user.");
                        break;
                    case IActivityManager.START_DELIVERED_TO_TOP:
                        System.err.println(
@@ -213,25 +212,36 @@ public class Am {
                                + "been delivered to currently running "
                                + "top-most instance.");
                        break;
                    case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                    case IActivityManager.START_RETURN_INTENT_TO_CALLER:
                        System.err.println(
                                "Error: Activity not started, you requested to "
                                + "both forward and receive its result");
                                "Warning: Activity not started because intent "
                                + "should be handled by the caller");
                        break;
                    case IActivityManager.START_TASK_TO_FRONT:
                        System.err.println(
                                "Warning: Activity not started, its current "
                                + "task has been brought to the front");
                        break;
                    case IActivityManager.START_INTENT_NOT_RESOLVED:
                        System.err.println(
                                "Error: Activity not started, unable to "
                                + "resolve " + intent.toString());
                        break;
                    case IActivityManager.START_RETURN_INTENT_TO_CALLER:
                    case IActivityManager.START_CLASS_NOT_FOUND:
                        System.err.println("Error type 3");
                        System.err.println("Error: Activity class " +
                                intent.getComponent().toShortString()
                                + " does not exist.");
                        break;
                    case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                        System.err.println(
                                "Warning: Activity not started because intent "
                                + "should be handled by the caller");
                                "Error: Activity not started, you requested to "
                                + "both forward and receive its result");
                        break;
                    case IActivityManager.START_TASK_TO_FRONT:
                    case IActivityManager.START_PERMISSION_DENIED:
                        System.err.println(
                                "Warning: Activity not started, its current "
                                + "task has been brought to the front");
                                "Error: Activity not started, you do not "
                                + "have permission to access it.");
                        break;
                    default:
                        System.err.println(
+34 −0
Original line number Diff line number Diff line
@@ -998,6 +998,20 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }
        
        case STOP_APP_SWITCHES_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            stopAppSwitches();
            reply.writeNoException();
            return true;
        }
        
        case RESUME_APP_SWITCHES_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            resumeAppSwitches();
            reply.writeNoException();
            return true;
        }
        
        case PEEK_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            Intent service = Intent.CREATOR.createFromParcel(data);
@@ -2182,5 +2196,25 @@ class ActivityManagerProxy implements IActivityManager
        return res;
    }
    
    public void stopAppSwitches() throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(STOP_APP_SWITCHES_TRANSACTION, data, reply, 0);
        reply.readException();
        reply.recycle();
        data.recycle();
    }
    
    public void resumeAppSwitches() throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(RESUME_APP_SWITCHES_TRANSACTION, data, reply, 0);
        reply.readException();
        reply.recycle();
        data.recycle();
    }
    
    private IBinder mRemote;
}
+26 −0
Original line number Diff line number Diff line
@@ -44,9 +44,30 @@ import java.util.List;
 * {@hide}
 */
public interface IActivityManager extends IInterface {
    /**
     * Returned by startActivity() if the start request was canceled because
     * app switches are temporarily canceled to ensure the user's last request
     * (such as pressing home) is performed.
     */
    public static final int START_SWITCHES_CANCELED = 4;
    /**
     * Returned by startActivity() if an activity wasn't really started, but
     * the given Intent was given to the existing top activity.
     */
    public static final int START_DELIVERED_TO_TOP = 3;
    /**
     * Returned by startActivity() if an activity wasn't really started, but
     * a task was simply brought to the foreground.
     */
    public static final int START_TASK_TO_FRONT = 2;
    /**
     * Returned by startActivity() if the caller asked that the Intent not
     * be executed if it is the recipient, and that is indeed the case.
     */
    public static final int START_RETURN_INTENT_TO_CALLER = 1;
    /**
     * Activity was started successfully as normal.
     */
    public static final int START_SUCCESS = 0;
    public static final int START_INTENT_NOT_RESOLVED = -1;
    public static final int START_CLASS_NOT_FOUND = -2;
@@ -225,6 +246,9 @@ public interface IActivityManager extends IInterface {
    
    public boolean shutdown(int timeout) throws RemoteException;
    
    public void stopAppSwitches() throws RemoteException;
    public void resumeAppSwitches() throws RemoteException;
    
    /*
     * Private non-Binder interfaces
     */
@@ -371,4 +395,6 @@ public interface IActivityManager extends IInterface {
    int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84;
    int PROFILE_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+85;
    int SHUTDOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+86;
    int STOP_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+87;
    int RESUME_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+88;
}
+11 −3
Original line number Diff line number Diff line
@@ -803,14 +803,22 @@
        android:description="@string/permdesc_runSetActivityWatcher"
        android:protectionLevel="signature" />

    <!-- Allows an application to watch and control how activities are
         started globally in the system.  Only for is in debugging
         (usually the monkey command). -->
    <!-- Allows an application to call the activity manager shutdown() API
         to put the higher-level system there into a shutdown state. -->
    <permission android:name="android.permission.SHUTDOWN"
        android:label="@string/permlab_shutdown"
        android:description="@string/permdesc_shutdown"
        android:protectionLevel="signature" />

    <!-- Allows an application to tell the activity manager to temporarily
         stop application switches, putting it into a special mode that
         prevents applications from immediately switching away from some
         critical UI such as the home screen. -->
    <permission android:name="android.permission.STOP_APP_SWITCHES"
        android:label="@string/permlab_stopAppSwitches"
        android:description="@string/permdesc_stopAppSwitches"
        android:protectionLevel="signature" />

    <!-- Allows an application to retrieve the current state of keys and
         switches.  This is only for use by the system.-->
    <permission android:name="android.permission.READ_INPUT_STATE"
+6 −0
Original line number Diff line number Diff line
@@ -472,6 +472,12 @@
    <string name="permdesc_shutdown">Puts the activity manager into a shutdown
        state.  Does not perform a complete shutdown.</string>

    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permlab_stopAppSwitches">prevent app switches</string>
    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permdesc_stopAppSwitches">Prevents the user from switching to
        another application.</string>

    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permlab_runSetActivityWatcher">monitor and control all application launching</string>
    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
Loading