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

Commit 574e6fd6 authored by Charlie Wang's avatar Charlie Wang Committed by Android (Google) Code Review
Browse files

Merge "Enable WearableSensingService."

parents 4b73fc64 ac20732c
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ import android.app.usage.StorageStatsManager;
import android.app.usage.UsageStatsManager;
import android.app.wallpapereffectsgeneration.IWallpaperEffectsGenerationManager;
import android.app.wallpapereffectsgeneration.WallpaperEffectsGenerationManager;
import android.app.wearable.IWearableSensingManager;
import android.app.wearable.WearableSensingManager;
import android.apphibernation.AppHibernationManager;
import android.appwidget.AppWidgetManager;
import android.bluetooth.BluetoothFrameworkInitializer;
@@ -1544,6 +1546,17 @@ public final class SystemServiceRegistry {
                                IAmbientContextManager.Stub.asInterface(iBinder);
                        return new AmbientContextManager(ctx.getOuterContext(), manager);
                    }});
        registerService(Context.WEARABLE_SENSING_SERVICE, WearableSensingManager.class,
                new CachedServiceFetcher<WearableSensingManager>() {
                    @Override
                    public WearableSensingManager createService(ContextImpl ctx)
                            throws ServiceNotFoundException {
                        IBinder iBinder = ServiceManager.getServiceOrThrow(
                                Context.WEARABLE_SENSING_SERVICE);
                        IWearableSensingManager manager =
                                IWearableSensingManager.Stub.asInterface(iBinder);
                        return new WearableSensingManager(ctx.getOuterContext(), manager);
                    }});

        sInitializing = true;
        try {
+28 −0
Original line number Diff line number Diff line
@@ -161,6 +161,32 @@ public class WearableSensingManagerService extends
        return null;
    }

    // Used in testing.
    void provideDataStream(@UserIdInt int userId, ParcelFileDescriptor parcelFileDescriptor,
            RemoteCallback callback) {
        synchronized (mLock) {
            final WearableSensingManagerPerUserService mService = getServiceForUserLocked(userId);
            if (mService != null) {
                mService.onProvideDataStream(parcelFileDescriptor, callback);
            } else {
                Slog.w(TAG, "Service not available.");
            }
        }
    }

    // Used in testing.
    void provideData(@UserIdInt int userId, PersistableBundle data, SharedMemory sharedMemory,
            RemoteCallback callback) {
        synchronized (mLock) {
            final WearableSensingManagerPerUserService mService = getServiceForUserLocked(userId);
            if (mService != null) {
                mService.onProvidedData(data, sharedMemory, callback);
            } else {
                Slog.w(TAG, "Service not available.");
            }
        }
    }

    private final class WearableSensingManagerInternal extends IWearableSensingManager.Stub {
        final WearableSensingManagerPerUserService mService = getServiceForUserLocked(
                UserHandle.getCallingUserId());
@@ -205,6 +231,8 @@ public class WearableSensingManagerService extends
        @Override
        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
            new WearableSensingShellCommand(WearableSensingManagerService.this).exec(
                    this, in, out, err, args, callback, resultReceiver);
        }
    }
}
+212 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wearable;

import android.annotation.NonNull;
import android.app.wearable.WearableSensingManager;
import android.content.ComponentName;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.RemoteCallback;
import android.os.ShellCommand;
import android.util.Slog;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

final class WearableSensingShellCommand extends ShellCommand {
    private static final String TAG = WearableSensingShellCommand.class.getSimpleName();

    static final TestableCallbackInternal sTestableCallbackInternal =
            new TestableCallbackInternal();

    @NonNull
    private final WearableSensingManagerService mService;

    private static ParcelFileDescriptor[] sPipe;

    WearableSensingShellCommand(@NonNull WearableSensingManagerService service) {
        mService = service;
    }

    /** Callbacks for WearableSensingService results used internally for testing. */
    static class TestableCallbackInternal {
        private int mLastStatus;

        public int getLastStatus() {
            return mLastStatus;
        }

        @NonNull
        private RemoteCallback createRemoteStatusCallback() {
            return new RemoteCallback(result -> {
                int status = result.getInt(WearableSensingManager.STATUS_RESPONSE_BUNDLE_KEY);
                final long token = Binder.clearCallingIdentity();
                try {
                    mLastStatus = status;
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            });
        }
    }

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
            return handleDefaultCommands(cmd);
        }

        switch (cmd) {
            case "create-data-stream":
                return createDataStream();
            case "destroy-data-stream":
                return destroyDataStream();
            case "provide-data-stream":
                return provideDataStream();
            case "write-to-data-stream":
                return writeToDataStream();
            case "provide-data":
                return provideData();
            case "get-last-status-code":
                return getLastStatusCode();
            case "get-bound-package":
                return getBoundPackageName();
            case "set-temporary-service":
                return setTemporaryService();
            default:
                return handleDefaultCommands(cmd);
        }
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
        pw.println("WearableSensingCommands commands: ");
        pw.println("  help");
        pw.println("    Print this help text.");
        pw.println();
        pw.println("  create-data-stream: Creates a data stream to be provided.");
        pw.println("  destroy-data-stream: Destroys a data stream if one was previously created.");
        pw.println("  provide-data-stream USER_ID: "
                + "Provides data stream to WearableSensingService.");
        pw.println("  write-to-data-stream STRING: writes string to data stream.");
        pw.println("  provide-data USER_ID KEY INTEGER: provide integer as data with key.");
        pw.println("  get-last-status-code: Prints the latest request status code.");
        pw.println("  get-bound-package USER_ID:"
                + "     Print the bound package that implements the service.");
        pw.println("  set-temporary-service USER_ID [PACKAGE_NAME] [COMPONENT_NAME DURATION]");
        pw.println("    Temporarily (for DURATION ms) changes the service implementation.");
        pw.println("    To reset, call with just the USER_ID argument.");
    }

    private int createDataStream() {
        Slog.d(TAG, "createDataStream");
        try {
            sPipe = ParcelFileDescriptor.createPipe();
        } catch (IOException e) {
            Slog.d(TAG, "Failed to createDataStream.", e);
        }
        return 0;
    }

    private int destroyDataStream() {
        Slog.d(TAG, "destroyDataStream");
        try {
            if (sPipe != null) {
                sPipe[0].close();
                sPipe[1].close();
            }
        } catch (IOException e) {
            Slog.d(TAG, "Failed to destroyDataStream.", e);
        }
        return 0;
    }

    private int provideDataStream() {
        Slog.d(TAG, "provideDataStream");
        if (sPipe != null) {
            final int userId = Integer.parseInt(getNextArgRequired());
            mService.provideDataStream(userId, sPipe[0],
                    sTestableCallbackInternal.createRemoteStatusCallback());
        }
        return 0;
    }

    private int writeToDataStream() {
        Slog.d(TAG, "writeToDataStream");
        if (sPipe != null) {
            final String value = getNextArgRequired();
            try {
                ParcelFileDescriptor writePipe = sPipe[1].dup();
                OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(writePipe);
                os.write(value.getBytes());
            } catch (IOException e) {
                Slog.d(TAG, "Failed to writeToDataStream.", e);
            }
        }
        return 0;
    }

    private int provideData() {
        Slog.d(TAG, "provideData");
        final int userId = Integer.parseInt(getNextArgRequired());
        final String key = getNextArgRequired();
        final int value = Integer.parseInt(getNextArgRequired());
        PersistableBundle data = new PersistableBundle();
        data.putInt(key, value);

        mService.provideData(userId, data, null,
                sTestableCallbackInternal.createRemoteStatusCallback());
        return 0;
    }

    private int getLastStatusCode() {
        Slog.d(TAG, "getLastStatusCode");
        final PrintWriter resultPrinter = getOutPrintWriter();
        int lastStatus = sTestableCallbackInternal.getLastStatus();
        resultPrinter.println(lastStatus);
        return 0;
    }

    private int setTemporaryService() {
        final PrintWriter out = getOutPrintWriter();
        final int userId = Integer.parseInt(getNextArgRequired());
        final String serviceName = getNextArg();
        if (serviceName == null) {
            mService.resetTemporaryService(userId);
            out.println("WearableSensingManagerService temporary reset. ");
            return 0;
        }

        final int duration = Integer.parseInt(getNextArgRequired());
        mService.setTemporaryService(userId, serviceName, duration);
        out.println("WearableSensingService temporarily set to " + serviceName
                + " for " + duration + "ms");
        return 0;
    }

    private int getBoundPackageName() {
        final PrintWriter resultPrinter = getOutPrintWriter();
        final int userId = Integer.parseInt(getNextArgRequired());
        final ComponentName componentName = mService.getComponentName(userId);
        resultPrinter.println(componentName == null ? "" : componentName.getPackageName());
        return 0;
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ import com.android.server.usage.UsageStatsService;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.vibrator.VibratorManagerService;
import com.android.server.vr.VrManagerService;
import com.android.server.wearable.WearableSensingManagerService;
import com.android.server.webkit.WebViewUpdateService;
import com.android.server.wm.ActivityTaskManagerService;
import com.android.server.wm.WindowManagerGlobalLock;
@@ -1830,6 +1831,7 @@ public final class SystemServer implements Dumpable {
            startSystemCaptionsManagerService(context, t);
            startTextToSpeechManagerService(context, t);
            startAmbientContextService(t);
            startWearableSensingService(t);

            // System Speech Recognition Service
            t.traceBegin("StartSpeechRecognitionManagerService");
@@ -3170,6 +3172,12 @@ public final class SystemServer implements Dumpable {
        t.traceEnd();
    }

    private void startWearableSensingService(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startWearableSensingService");
        mSystemServiceManager.startService(WearableSensingManagerService.class);
        t.traceEnd();
    }

    private static void startSystemUi(Context context, WindowManagerService windowManager) {
        PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
        Intent intent = new Intent();