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

Commit db69a7da authored by Andrii Kulian's avatar Andrii Kulian Committed by Automerger Merge Worker
Browse files

Merge "Add sample WM Jetpack Extensions impl" into sc-dev am: 90f1b95c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13467359

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ie54a2e830962bd934cbd6c57a47da78be3643058
parents 185483b2 90f1b95c
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Sidecar
android_library_import {
    name: "window-sidecar",
    aars: ["window-sidecar-release.aar"],
@@ -20,7 +21,7 @@ android_library_import {

java_library {
    name: "androidx.window.sidecar",
    srcs: ["src/**/*.java"],
    srcs: ["src/androidx/window/sidecar/**/*.java", "src/androidx/window/util/**/*.java"],
    static_libs: ["window-sidecar"],
    installable: true,
    sdk_version: "core_platform",
@@ -36,3 +37,31 @@ prebuilt_etc {
    src: "androidx.window.sidecar.xml",
    filename_from_src: true,
}

// Extensions
// NOTE: This module is still under active development and must not
// be used in production. Use 'androidx.window.sidecar' instead.
android_library_import {
    name: "window-extensions",
    aars: ["window-extensions-release.aar"],
    sdk_version: "current",
}

java_library {
    name: "androidx.window.extensions",
    srcs: ["src/androidx/window/extensions/**/*.java", "src/androidx/window/util/**/*.java"],
    static_libs: ["window-extensions"],
    installable: true,
    sdk_version: "core_platform",
    system_ext_specific: true,
    libs: ["framework", "androidx.annotation_annotation",],
    required: ["androidx.window.extensions.xml",],
}

prebuilt_etc {
    name: "androidx.window.extensions.xml",
    system_ext_specific: true,
    sub_dir: "permissions",
    src: "androidx.window.extensions.xml",
    filename_from_src: true,
}
+21 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2021 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.
  -->
<permissions>
    <library
        name="androidx.window.extensions"
        file="/system_ext/framework/androidx.window.extensions.jar"/>
</permissions>
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 androidx.window.extensions;

import android.content.Context;

/**
 * Provider class that will instantiate the library implementation. It must be included in the
 * vendor library, and the vendor implementation must match the signature of this class.
 */
public class ExtensionProvider {
    /**
     * Provides a simple implementation of {@link ExtensionInterface} that can be replaced by
     * an OEM by overriding this method.
     */
    public static ExtensionInterface getExtensionImpl(Context context) {
        return new SampleExtensionImpl(context);
    }

    /**
     * The support library will use this method to check API version compatibility.
     * @return API version string in MAJOR.MINOR.PATCH-description format.
     */
    public static String getApiVersion() {
        return "1.0.0-settings_sample";
    }
}
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 androidx.window.extensions;

import static android.view.Display.DEFAULT_DISPLAY;

import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.window.util.BaseDisplayFeature;
import androidx.window.util.SettingsConfigProvider;

import java.util.ArrayList;
import java.util.List;

/**
 * Reference implementation of androidx.window.extensions OEM interface for use with
 * WindowManager Jetpack.
 *
 * NOTE: This version is a work in progress and under active development. It MUST NOT be used in
 * production builds since the interface can still change before reaching stable version.
 * Please refer to {@link androidx.window.sidecar.SampleSidecarImpl} instead.
 */
class SampleExtensionImpl extends StubExtension implements
        SettingsConfigProvider.StateChangeCallback {
    private static final String TAG = "SampleExtension";

    private final SettingsConfigProvider mConfigProvider;

    SampleExtensionImpl(Context context) {
        mConfigProvider = new SettingsConfigProvider(context, this);
    }

    @Override
    public void onDevicePostureChanged() {
        updateDeviceState(new ExtensionDeviceState(mConfigProvider.getDeviceState()));
    }

    @Override
    public void onDisplayFeaturesChanged() {
        for (Activity activity : getActivitiesListeningForLayoutChanges()) {
            ExtensionWindowLayoutInfo newLayout = getWindowLayoutInfo(activity);
            updateWindowLayout(activity, newLayout);
        }
    }

    @NonNull
    private ExtensionWindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) {
        List<ExtensionDisplayFeature> displayFeatures = getDisplayFeatures(activity);
        return new ExtensionWindowLayoutInfo(displayFeatures);
    }

    private List<ExtensionDisplayFeature> getDisplayFeatures(@NonNull Activity activity) {
        List<ExtensionDisplayFeature> features = new ArrayList<>();
        int displayId = activity.getDisplayId();
        if (displayId != DEFAULT_DISPLAY) {
            Log.w(TAG, "This sample doesn't support display features on secondary displays");
            return features;
        }

        if (activity.isInMultiWindowMode()) {
            // It is recommended not to report any display features in multi-window mode, since it
            // won't be possible to synchronize the display feature positions with window movement.
            return features;
        }

        List<BaseDisplayFeature> storedFeatures = mConfigProvider.getDisplayFeatures();
        for (BaseDisplayFeature baseFeature : storedFeatures) {
            Rect featureRect = baseFeature.getRect();
            rotateRectToDisplayRotation(displayId, featureRect);
            transformToWindowSpaceRect(activity, featureRect);
            features.add(new ExtensionFoldingFeature(featureRect, baseFeature.getType(),
                    baseFeature.getState()));
        }
        return features;
    }

    @Override
    protected void onListenersChanged() {
        if (hasListeners()) {
            mConfigProvider.registerObserversIfNeeded();
        } else {
            mConfigProvider.unregisterObserversIfNeeded();
        }

        onDevicePostureChanged();
        onDisplayFeaturesChanged();
    }
}
+86 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 androidx.window.extensions;

import android.app.Activity;

import androidx.annotation.NonNull;

import java.util.HashSet;
import java.util.Set;

/**
 * Basic implementation of the {@link ExtensionInterface}. An OEM can choose to use it as the base
 * class for their implementation.
 */
abstract class StubExtension implements ExtensionInterface {

    private ExtensionCallback mExtensionCallback;
    private final Set<Activity> mWindowLayoutChangeListenerActivities = new HashSet<>();
    private boolean mDeviceStateChangeListenerRegistered;

    StubExtension() {
    }

    @Override
    public void setExtensionCallback(@NonNull ExtensionCallback extensionCallback) {
        this.mExtensionCallback = extensionCallback;
    }

    @Override
    public void onWindowLayoutChangeListenerAdded(@NonNull Activity activity) {
        this.mWindowLayoutChangeListenerActivities.add(activity);
        this.onListenersChanged();
    }

    @Override
    public void onWindowLayoutChangeListenerRemoved(@NonNull Activity activity) {
        this.mWindowLayoutChangeListenerActivities.remove(activity);
        this.onListenersChanged();
    }

    @Override
    public void onDeviceStateListenersChanged(boolean isEmpty) {
        this.mDeviceStateChangeListenerRegistered = !isEmpty;
        this.onListenersChanged();
    }

    void updateDeviceState(ExtensionDeviceState newState) {
        if (this.mExtensionCallback != null) {
            mExtensionCallback.onDeviceStateChanged(newState);
        }
    }

    void updateWindowLayout(@NonNull Activity activity,
            @NonNull ExtensionWindowLayoutInfo newLayout) {
        if (this.mExtensionCallback != null) {
            mExtensionCallback.onWindowLayoutChanged(activity, newLayout);
        }
    }

    @NonNull
    Set<Activity> getActivitiesListeningForLayoutChanges() {
        return mWindowLayoutChangeListenerActivities;
    }

    protected boolean hasListeners() {
        return !mWindowLayoutChangeListenerActivities.isEmpty()
                || mDeviceStateChangeListenerRegistered;
    }

    protected abstract void onListenersChanged();
}
Loading