1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.car.projection; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.app.ActivityOptions; 24 import android.car.annotation.AddedInOrBefore; 25 import android.car.builtin.app.ActivityManagerHelper; 26 import android.content.ComponentName; 27 import android.os.Bundle; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 32 /** 33 * This class holds OEM customization for projection receiver app. It is created by Car Service. 34 * 35 * @hide 36 */ 37 @SystemApi 38 public class ProjectionOptions { 39 private static final String KEY_PREFIX = "android.car.projection."; 40 41 /** Immersive full screen mode (all system bars are hidden) */ 42 @AddedInOrBefore(majorVersion = 33) 43 public static final int UI_MODE_FULL_SCREEN = 0; 44 45 /** Show status and navigation bars. */ 46 @AddedInOrBefore(majorVersion = 33) 47 public static final int UI_MODE_BLENDED = 1; 48 49 private static final int UI_MODE_DEFAULT = UI_MODE_FULL_SCREEN; 50 51 /** @hide */ 52 @IntDef({UI_MODE_FULL_SCREEN, UI_MODE_BLENDED}) 53 @Retention(RetentionPolicy.SOURCE) 54 public @interface ProjectionUiMode {} 55 56 /** Indicates that head unit didn't specify information about access point mode. This value 57 * can only be seen on Android SDK 31 and below. */ 58 @AddedInOrBefore(majorVersion = 33) 59 public static final int AP_MODE_NOT_SPECIFIED = 0; 60 61 /** Projection access point was created such that it may provide Internet access. */ 62 @AddedInOrBefore(majorVersion = 33) 63 public static final int AP_MODE_TETHERED = 1; 64 65 /** 66 * Projection access point was created as local-only hotspot, without Internet access and the 67 * credentials will be auto-generated for every access point initialization. 68 */ 69 @AddedInOrBefore(majorVersion = 33) 70 public static final int AP_MODE_LOHS_DYNAMIC_CREDENTIALS = 2; 71 72 /** 73 * Projection access point was created as local-only hotspot, without Internet access and the 74 * credentials will persist reboots. Credentials still can be reseted by user or app request. 75 */ 76 @AddedInOrBefore(majorVersion = 33) 77 public static final int AP_MODE_LOHS_STATIC_CREDENTIALS = 3; 78 79 /** @hide */ 80 @IntDef({AP_MODE_NOT_SPECIFIED, AP_MODE_TETHERED, AP_MODE_LOHS_DYNAMIC_CREDENTIALS, 81 AP_MODE_LOHS_STATIC_CREDENTIALS}) 82 @Retention(RetentionPolicy.SOURCE) 83 public @interface ProjectionAccessPointMode {} 84 85 private static final String KEY_ACTIVITY_OPTIONS = KEY_PREFIX + "activityOptions"; 86 private static final String KEY_UI_MODE = KEY_PREFIX + "systemUiFlags"; 87 private static final String KEY_CONSENT_ACTIVITY = KEY_PREFIX + "consentActivity"; 88 private static final String KEY_ACCESS_POINT_MODE = KEY_PREFIX + "ap_mode"; 89 90 private final ActivityOptions mActivityOptions; 91 private final int mUiMode; 92 private final ComponentName mConsentActivity; 93 private final int mApMode; 94 95 /** 96 * Creates new instance for given {@code Bundle} 97 * 98 * @param bundle contains OEM specific information 99 */ ProjectionOptions(Bundle bundle)100 public ProjectionOptions(Bundle bundle) { 101 Bundle activityOptionsBundle = bundle.getBundle(KEY_ACTIVITY_OPTIONS); 102 mActivityOptions = activityOptionsBundle != null 103 ? ActivityManagerHelper.createActivityOptions(activityOptionsBundle) : null; 104 mUiMode = bundle.getInt(KEY_UI_MODE, UI_MODE_DEFAULT); 105 mConsentActivity = bundle.getParcelable(KEY_CONSENT_ACTIVITY); 106 mApMode = bundle.getInt(KEY_ACCESS_POINT_MODE, AP_MODE_NOT_SPECIFIED); 107 } 108 ProjectionOptions(Builder builder)109 private ProjectionOptions(Builder builder) { 110 mActivityOptions = builder.mActivityOptions; 111 mUiMode = builder.mUiMode; 112 mConsentActivity = builder.mConsentActivity; 113 mApMode = builder.mApMode; 114 } 115 116 /** 117 * Returns combination of flags from View.SYSTEM_UI_FLAG_* which will be used by projection 118 * receiver app during rendering. 119 */ 120 @AddedInOrBefore(majorVersion = 33) getUiMode()121 public @ProjectionUiMode int getUiMode() { 122 return mUiMode; 123 } 124 125 /** 126 * Returns projection access point mode. 127 * 128 * <p>The result could be one of the following values: 129 * <ul> 130 * <li>{@link #AP_MODE_NOT_SPECIFIED}</li> 131 * <li>{@link #AP_MODE_TETHERED}</li> 132 * <li>{@link #AP_MODE_LOHS_DYNAMIC_CREDENTIALS}</li> 133 * <li>{@link #AP_MODE_LOHS_STATIC_CREDENTIALS}</li> 134 * </ul> 135 */ 136 @AddedInOrBefore(majorVersion = 33) getProjectionAccessPointMode()137 public @ProjectionAccessPointMode int getProjectionAccessPointMode() { 138 return mApMode; 139 } 140 141 /** 142 * Returns {@link ActivityOptions} that needs to be applied when launching projection activity 143 */ 144 @AddedInOrBefore(majorVersion = 33) getActivityOptions()145 public @Nullable ActivityOptions getActivityOptions() { 146 return mActivityOptions; 147 } 148 149 /** 150 * Returns package/activity name of the consent activity provided by OEM which needs to be shown 151 * for all mobile devices unless user accepted the consent. 152 * 153 * <p>If the method returns null then consent dialog should not be shown. 154 */ 155 @AddedInOrBefore(majorVersion = 33) getConsentActivity()156 public @Nullable ComponentName getConsentActivity() { 157 return mConsentActivity; 158 } 159 160 /** Converts current object to {@link Bundle} */ 161 @AddedInOrBefore(majorVersion = 33) toBundle()162 public @NonNull Bundle toBundle() { 163 Bundle bundle = new Bundle(); 164 if (mActivityOptions != null) { 165 bundle.putBundle(KEY_ACTIVITY_OPTIONS, mActivityOptions.toBundle()); 166 } 167 bundle.putParcelable(KEY_CONSENT_ACTIVITY, mConsentActivity); 168 if (mUiMode != UI_MODE_DEFAULT) { 169 bundle.putInt(KEY_UI_MODE, mUiMode); 170 } 171 bundle.putInt(KEY_ACCESS_POINT_MODE, mApMode); 172 return bundle; 173 } 174 175 /** @hide */ 176 @AddedInOrBefore(majorVersion = 33) builder()177 public static Builder builder() { 178 return new Builder(); 179 } 180 181 /** @hide */ 182 public static class Builder { 183 private ActivityOptions mActivityOptions; 184 private int mUiMode = UI_MODE_DEFAULT; 185 private ComponentName mConsentActivity; 186 private int mApMode = AP_MODE_NOT_SPECIFIED; 187 188 /** Sets {@link ActivityOptions} to launch projection activity. */ 189 @AddedInOrBefore(majorVersion = 33) setProjectionActivityOptions(ActivityOptions activityOptions)190 public Builder setProjectionActivityOptions(ActivityOptions activityOptions) { 191 mActivityOptions = activityOptions; 192 return this; 193 } 194 195 /** Set UI for projection activity. It can be one of {@code UI_MODE_*} constants. */ 196 @AddedInOrBefore(majorVersion = 33) setUiMode(@rojectionUiMode int uiMode)197 public Builder setUiMode(@ProjectionUiMode int uiMode) { 198 mUiMode = uiMode; 199 return this; 200 } 201 202 /** Sets consent activity which will be shown before starting projection. */ 203 @AddedInOrBefore(majorVersion = 33) setConsentActivity(ComponentName consentActivity)204 public Builder setConsentActivity(ComponentName consentActivity) { 205 mConsentActivity = consentActivity; 206 return this; 207 } 208 209 /** Sets projection access point mode */ 210 @AddedInOrBefore(majorVersion = 33) setAccessPointMode(@rojectionAccessPointMode int accessPointMode)211 public Builder setAccessPointMode(@ProjectionAccessPointMode int accessPointMode) { 212 this.mApMode = accessPointMode; 213 return this; 214 } 215 216 /** Creates an instance of {@link android.car.projection.ProjectionOptions} */ 217 @AddedInOrBefore(majorVersion = 33) build()218 public ProjectionOptions build() { 219 return new ProjectionOptions(this); 220 } 221 } 222 223 /** @hide */ 224 @Override 225 @AddedInOrBefore(majorVersion = 33) toString()226 public String toString() { 227 return toBundle().toString(); 228 } 229 } 230