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

Commit 16f7cdf2 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

First pass of "fake" services on Ravenwood.

One of our eventual goals with Ravenwood is to support usage of
system services from test code.  A recent change added support for
"real" services on Ravenwood, and this change expands that to add
support for "fake" services.

Some services are so tangled with dependencies it would take a
long time until we'd be able to run their "real" code.  Also, some
services with deep hardware dependencies that it can be difficult
to add new abstraction layers to support Ravenwood.  Finally, we
want to support service owners that only have resources to meet
the "Pareto principle", where enabling 20% of their functionality
on Ravenwood is enough to unblock 80% of test use-cases.

Thus, we're supporting teams bringing either "real" or "fake"
implementations of their services.  Since all test interactions
still go through published FooManager and FooManagerInternal-style
interfaces, teams can start with a "fake" and slowly transition
to using more of their "real" code over time, without having to
update test clients.

And as a final reminder, because Ravenwood requires test suites
like CTS, we're already verifying that "fake" services behave
similarly to the "real" services on physical devices.

Bug: 325506297
Test: atest CtsContentTestCasesRavenwood
Change-Id: I8ed5bd030e03143c15cb9fa945bbdcb0b412611e
parent 2f6d3430
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -144,6 +144,16 @@ java_library {
    jarjar_rules: ":ravenwood-services-jarjar-rules",
}

java_library {
    name: "services.fakes.ravenwood-jarjar",
    installable: false,
    srcs: [":services.fakes-sources"],
    libs: [
        "services.core.ravenwood",
    ],
    jarjar_rules: ":ravenwood-services-jarjar-rules",
}

java_library {
    name: "mockito-ravenwood-prebuilt",
    installable: false,
@@ -189,6 +199,7 @@ android_ravenwood_libgroup {
        "ravenwood-helper-runtime",
        "hoststubgen-helper-runtime.ravenwood",
        "services.core.ravenwood-jarjar",
        "services.fakes.ravenwood-jarjar",

        // Provide runtime versions of utils linked in below
        "junit",
+24 −10
Original line number Diff line number Diff line
@@ -169,6 +169,8 @@ import java.util.List;
 */
@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ClipData implements Parcelable {
    private static final String TAG = "ClipData";

    static final String[] MIMETYPES_TEXT_PLAIN = new String[] {
        ClipDescription.MIMETYPE_TEXT_PLAIN };
    static final String[] MIMETYPES_TEXT_HTML = new String[] {
@@ -476,7 +478,6 @@ public class ClipData implements Parcelable {
         * @return Returns the item's textual representation.
         */
//BEGIN_INCLUDE(coerceToText)
        @android.ravenwood.annotation.RavenwoodThrow
        public CharSequence coerceToText(Context context) {
            // If this Item has an explicit textual value, simply return that.
            CharSequence text = getText();
@@ -484,13 +485,20 @@ public class ClipData implements Parcelable {
                return text;
            }

            // Gracefully handle cases where resolver isn't available
            ContentResolver resolver = null;
            try {
                resolver = context.getContentResolver();
            } catch (Exception e) {
                Log.w(TAG, "Failed to obtain ContentResolver: " + e);
            }

            // If this Item has a URI value, try using that.
            Uri uri = getUri();
            if (uri != null) {
            if (uri != null && resolver != null) {
                // First see if the URI can be opened as a plain text stream
                // (of any sub-type).  If so, this is the best textual
                // representation for it.
                final ContentResolver resolver = context.getContentResolver();
                AssetFileDescriptor descr = null;
                FileInputStream stream = null;
                InputStreamReader reader = null;
@@ -499,7 +507,7 @@ public class ClipData implements Parcelable {
                        // Ask for a stream of the desired type.
                        descr = resolver.openTypedAssetFileDescriptor(uri, "text/*", null);
                    } catch (SecurityException e) {
                        Log.w("ClipData", "Failure opening stream", e);
                        Log.w(TAG, "Failure opening stream", e);
                    } catch (FileNotFoundException|RuntimeException e) {
                        // Unable to open content URI as text...  not really an
                        // error, just something to ignore.
@@ -519,7 +527,7 @@ public class ClipData implements Parcelable {
                            return builder.toString();
                        } catch (IOException e) {
                            // Something bad has happened.
                            Log.w("ClipData", "Failure loading text", e);
                            Log.w(TAG, "Failure loading text", e);
                            return e.toString();
                        }
                    }
@@ -528,7 +536,8 @@ public class ClipData implements Parcelable {
                    IoUtils.closeQuietly(stream);
                    IoUtils.closeQuietly(reader);
                }

            }
            if (uri != null) {
                // If we couldn't open the URI as a stream, use the URI itself as a textual
                // representation (but not for "content", "android.resource" or "file" schemes).
                final String scheme = uri.getScheme();
@@ -704,7 +713,7 @@ public class ClipData implements Parcelable {
                        }

                    } catch (SecurityException e) {
                        Log.w("ClipData", "Failure opening stream", e);
                        Log.w(TAG, "Failure opening stream", e);

                    } catch (FileNotFoundException e) {
                        // Unable to open content URI as text...  not really an
@@ -712,7 +721,7 @@ public class ClipData implements Parcelable {

                    } catch (IOException e) {
                        // Something bad has happened.
                        Log.w("ClipData", "Failure loading text", e);
                        Log.w(TAG, "Failure loading text", e);
                        return Html.escapeHtml(e.toString());

                    } finally {
@@ -1123,7 +1132,7 @@ public class ClipData implements Parcelable {
     *
     * @hide
     */
    @android.ravenwood.annotation.RavenwoodThrow
    @android.ravenwood.annotation.RavenwoodKeep
    public void prepareToLeaveProcess(boolean leavingPackage) {
        // Assume that callers are going to be granting permissions
        prepareToLeaveProcess(leavingPackage, Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -1134,7 +1143,7 @@ public class ClipData implements Parcelable {
     *
     * @hide
     */
    @android.ravenwood.annotation.RavenwoodThrow
    @android.ravenwood.annotation.RavenwoodReplace
    public void prepareToLeaveProcess(boolean leavingPackage, int intentFlags) {
        final int size = mItems.size();
        for (int i = 0; i < size; i++) {
@@ -1154,6 +1163,11 @@ public class ClipData implements Parcelable {
        }
    }

    /** @hide */
    public void prepareToLeaveProcess$ravenwood(boolean leavingPackage, int intentFlags) {
        // No process boundaries on Ravenwood; ignored
    }

    /** {@hide} */
    @android.ravenwood.annotation.RavenwoodThrow
    public void prepareToEnterProcess(AttributionSource source) {
+3 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import java.util.Objects;
 * </div>
 */
@SystemService(Context.CLIPBOARD_SERVICE)
@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ClipboardManager extends android.text.ClipboardManager {

    /**
@@ -143,6 +144,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION)
    @android.ravenwood.annotation.RavenwoodThrow
    public boolean areClipboardAccessNotificationsEnabled() {
        try {
            return mService.areClipboardAccessNotificationsEnabledForUser(mContext.getUserId());
@@ -159,6 +161,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION)
    @android.ravenwood.annotation.RavenwoodThrow
    public void setClipboardAccessNotificationsEnabled(boolean enable) {
        try {
            mService.setClipboardAccessNotificationsEnabledForUser(enable, mContext.getUserId());
+16 −1
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;

import java.util.concurrent.Executor;

/**
 * A {@link Thread} that has a {@link Looper}.
 * The {@link Looper} can then be used to create {@link Handler}s.
@@ -30,7 +32,8 @@ public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;
    private volatile @Nullable Handler mHandler;
    private volatile @Nullable Executor mExecutor;

    public HandlerThread(String name) {
        super(name);
@@ -130,6 +133,18 @@ public class HandlerThread extends Thread {
        return mHandler;
    }

    /**
     * @return a shared {@link Executor} associated with this thread
     * @hide
     */
    @NonNull
    public Executor getThreadExecutor() {
        if (mExecutor == null) {
            mExecutor = new HandlerExecutor(getThreadHandler());
        }
        return mExecutor;
    }

    /**
     * Quits the handler thread's looper.
     * <p>
+2 −0
Original line number Diff line number Diff line
@@ -55,3 +55,5 @@ class android.content.Context stub
    method getSystemService (Ljava/lang/Class;)Ljava/lang/Object; stub
class android.content.pm.PackageManager stub
    method <init> ()V stub
class android.text.ClipboardManager stub
    method <init> ()V stub
Loading