861 lines
31 KiB
Java
861 lines
31 KiB
Java
![]() |
/**
|
||
|
* Copyright (c) 2015, 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 android.app;
|
||
|
|
||
|
import static com.android.internal.util.Preconditions.checkArgument;
|
||
|
|
||
|
import android.annotation.DrawableRes;
|
||
|
import android.annotation.FlaggedApi;
|
||
|
import android.annotation.IntDef;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.app.NotificationManager.InterruptionFilter;
|
||
|
import android.content.ComponentName;
|
||
|
import android.net.Uri;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
import android.service.notification.Condition;
|
||
|
import android.service.notification.ZenDeviceEffects;
|
||
|
import android.service.notification.ZenPolicy;
|
||
|
import android.view.WindowInsetsController;
|
||
|
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/**
|
||
|
* Rule instance information for a zen (aka DND or Attention Management) mode.
|
||
|
*/
|
||
|
public final class AutomaticZenRule implements Parcelable {
|
||
|
/* @hide */
|
||
|
private static final int ENABLED = 1;
|
||
|
/* @hide */
|
||
|
private static final int DISABLED = 0;
|
||
|
|
||
|
/**
|
||
|
* Rule is of an unknown type. This is the default value if not provided by the owning app,
|
||
|
* and the value returned if the true type was added in an API level lower than the calling
|
||
|
* app's targetSdk.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_UNKNOWN = -1;
|
||
|
/**
|
||
|
* Rule is of a known type, but not one of the specific types.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_OTHER = 0;
|
||
|
/**
|
||
|
* The type for rules triggered according to a time-based schedule.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_SCHEDULE_TIME = 1;
|
||
|
/**
|
||
|
* The type for rules triggered by calendar events.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_SCHEDULE_CALENDAR = 2;
|
||
|
/**
|
||
|
* The type for rules triggered by bedtime/sleeping, like time of day, or snore detection.
|
||
|
*
|
||
|
* <p>Only the 'Wellbeing' app may own rules of this type.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_BEDTIME = 3;
|
||
|
/**
|
||
|
* The type for rules triggered by driving detection, like Bluetooth connections or vehicle
|
||
|
* sounds.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_DRIVING = 4;
|
||
|
/**
|
||
|
* The type for rules triggered by the user entering an immersive activity, like opening an app
|
||
|
* using {@link WindowInsetsController#hide(int)}.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_IMMERSIVE = 5;
|
||
|
/**
|
||
|
* The type for rules that have a {@link ZenPolicy} that implies that the
|
||
|
* device should not make sound and potentially hide some visual effects; may be triggered
|
||
|
* when entering a location where silence is requested, like a theater.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_THEATER = 6;
|
||
|
/**
|
||
|
* The type for rules created and managed by a device owner. These rules may not be fully
|
||
|
* editable by the device user.
|
||
|
*
|
||
|
* <p>Only a 'Device Owner' app may own rules of this type.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int TYPE_MANAGED = 7;
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(prefix = { "TYPE_" }, value = {
|
||
|
TYPE_UNKNOWN, TYPE_OTHER, TYPE_SCHEDULE_TIME, TYPE_SCHEDULE_CALENDAR, TYPE_BEDTIME,
|
||
|
TYPE_DRIVING, TYPE_IMMERSIVE, TYPE_THEATER, TYPE_MANAGED
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface Type {}
|
||
|
|
||
|
/**
|
||
|
* Enum for the user-modifiable fields in this object.
|
||
|
* @hide
|
||
|
*/
|
||
|
@IntDef(flag = true, prefix = { "FIELD_" }, value = {
|
||
|
FIELD_NAME,
|
||
|
FIELD_INTERRUPTION_FILTER,
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface ModifiableField {}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int FIELD_NAME = 1 << 0;
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final int FIELD_INTERRUPTION_FILTER = 1 << 1;
|
||
|
|
||
|
private boolean enabled;
|
||
|
private String name;
|
||
|
private @InterruptionFilter int interruptionFilter;
|
||
|
private Uri conditionId;
|
||
|
private ComponentName owner;
|
||
|
private ComponentName configurationActivity;
|
||
|
private long creationTime;
|
||
|
private ZenPolicy mZenPolicy;
|
||
|
private ZenDeviceEffects mDeviceEffects;
|
||
|
// TODO: b/310620812 - Remove this once FLAG_MODES_API is inlined.
|
||
|
private boolean mModified = false;
|
||
|
private String mPkg;
|
||
|
private int mType = Flags.modesApi() ? TYPE_UNKNOWN : 0;
|
||
|
private int mIconResId;
|
||
|
private String mTriggerDescription;
|
||
|
private boolean mAllowManualInvocation;
|
||
|
|
||
|
/**
|
||
|
* The maximum string length for any string contained in this automatic zen rule. This pertains
|
||
|
* both to fields in the rule itself (such as its name) and items with sub-fields.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int MAX_STRING_LENGTH = 1000;
|
||
|
|
||
|
/**
|
||
|
* The maximum string length for the trigger description rule, given UI constraints.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int MAX_DESC_LENGTH = 150;
|
||
|
|
||
|
/**
|
||
|
* Creates an automatic zen rule.
|
||
|
*
|
||
|
* @param name The name of the rule.
|
||
|
* @param owner The Condition Provider service that owns this rule.
|
||
|
* @param interruptionFilter The interruption filter defines which notifications are allowed to
|
||
|
* interrupt the user (e.g. via sound & vibration) while this rule
|
||
|
* is active.
|
||
|
* @param enabled Whether the rule is enabled.
|
||
|
*
|
||
|
* @deprecated Use {@link AutomaticZenRule.Builder} to construct an {@link AutomaticZenRule}.
|
||
|
*/
|
||
|
@Deprecated
|
||
|
public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
|
||
|
int interruptionFilter, boolean enabled) {
|
||
|
this(name, owner, null, conditionId, null, interruptionFilter, enabled);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an automatic zen rule.
|
||
|
*
|
||
|
* <p>Note: Prefer {@link AutomaticZenRule.Builder} to construct an {@link AutomaticZenRule}.
|
||
|
*
|
||
|
* @param name The name of the rule.
|
||
|
* @param owner The Condition Provider service that owns this rule. This can be null if you're
|
||
|
* using {@link NotificationManager#setAutomaticZenRuleState(String, Condition)}
|
||
|
* instead of {@link android.service.notification.ConditionProviderService}.
|
||
|
* @param configurationActivity An activity that handles
|
||
|
* {@link NotificationManager#ACTION_AUTOMATIC_ZEN_RULE} that shows
|
||
|
* the user
|
||
|
* more information about this rule and/or allows them to
|
||
|
* configure it. This is required if you are not using a
|
||
|
* {@link android.service.notification.ConditionProviderService}.
|
||
|
* If you are, it overrides the information specified in your
|
||
|
* manifest.
|
||
|
* @param conditionId A representation of the state that should cause your app to apply the
|
||
|
* given interruption filter.
|
||
|
* @param interruptionFilter The interruption filter defines which notifications are allowed to
|
||
|
* interrupt the user (e.g. via sound & vibration) while this rule
|
||
|
* is active.
|
||
|
* @param policy The policy defines which notifications are allowed to interrupt the user
|
||
|
* while this rule is active. This overrides the global policy while this rule is
|
||
|
* action ({@link Condition#STATE_TRUE}).
|
||
|
* @param enabled Whether the rule is enabled.
|
||
|
*/
|
||
|
public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
|
||
|
@Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
|
||
|
@Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
|
||
|
this.name = getTrimmedString(name);
|
||
|
this.owner = getTrimmedComponentName(owner);
|
||
|
this.configurationActivity = getTrimmedComponentName(configurationActivity);
|
||
|
this.conditionId = getTrimmedUri(conditionId);
|
||
|
this.interruptionFilter = interruptionFilter;
|
||
|
this.enabled = enabled;
|
||
|
this.mZenPolicy = policy;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
// TODO: b/310620812 - Remove when the flag is inlined (all system callers should use Builder).
|
||
|
public AutomaticZenRule(String name, ComponentName owner, ComponentName configurationActivity,
|
||
|
Uri conditionId, ZenPolicy policy, int interruptionFilter, boolean enabled,
|
||
|
long creationTime) {
|
||
|
this(name, owner, configurationActivity, conditionId, policy, interruptionFilter, enabled);
|
||
|
this.creationTime = creationTime;
|
||
|
}
|
||
|
|
||
|
public AutomaticZenRule(Parcel source) {
|
||
|
enabled = source.readInt() == ENABLED;
|
||
|
if (source.readInt() == ENABLED) {
|
||
|
name = getTrimmedString(source.readString());
|
||
|
}
|
||
|
interruptionFilter = source.readInt();
|
||
|
conditionId = getTrimmedUri(source.readParcelable(null, android.net.Uri.class));
|
||
|
owner = getTrimmedComponentName(
|
||
|
source.readParcelable(null, android.content.ComponentName.class));
|
||
|
configurationActivity = getTrimmedComponentName(
|
||
|
source.readParcelable(null, android.content.ComponentName.class));
|
||
|
creationTime = source.readLong();
|
||
|
mZenPolicy = source.readParcelable(null, ZenPolicy.class);
|
||
|
mModified = source.readInt() == ENABLED;
|
||
|
mPkg = source.readString();
|
||
|
if (Flags.modesApi()) {
|
||
|
mDeviceEffects = source.readParcelable(null, ZenDeviceEffects.class);
|
||
|
mAllowManualInvocation = source.readBoolean();
|
||
|
mIconResId = source.readInt();
|
||
|
mTriggerDescription = getTrimmedString(source.readString(), MAX_DESC_LENGTH);
|
||
|
mType = source.readInt();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the {@link ComponentName} of the condition provider service that owns this rule.
|
||
|
*/
|
||
|
public ComponentName getOwner() {
|
||
|
return owner;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the {@link ComponentName} of the activity that shows configuration options
|
||
|
* for this rule.
|
||
|
*/
|
||
|
public @Nullable ComponentName getConfigurationActivity() {
|
||
|
return configurationActivity;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the representation of the state that causes this rule to become active.
|
||
|
*/
|
||
|
public Uri getConditionId() {
|
||
|
return conditionId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the interruption filter that is applied when this rule is active.
|
||
|
*/
|
||
|
public int getInterruptionFilter() {
|
||
|
return interruptionFilter;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the name of this rule.
|
||
|
*/
|
||
|
public String getName() {
|
||
|
return name;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether this rule is enabled.
|
||
|
*/
|
||
|
public boolean isEnabled() {
|
||
|
return enabled;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether this rule's name has been modified by the user.
|
||
|
* @hide
|
||
|
*/
|
||
|
// TODO: b/310620812 - Consider removing completely. Seems not be used anywhere except tests.
|
||
|
public boolean isModified() {
|
||
|
return mModified;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the zen policy.
|
||
|
*/
|
||
|
@Nullable
|
||
|
public ZenPolicy getZenPolicy() {
|
||
|
return mZenPolicy == null ? null : this.mZenPolicy.copy();
|
||
|
}
|
||
|
|
||
|
/** Gets the {@link ZenDeviceEffects} of this rule. */
|
||
|
@Nullable
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public ZenDeviceEffects getDeviceEffects() {
|
||
|
return mDeviceEffects;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the time this rule was created, represented as milliseconds since the epoch.
|
||
|
*/
|
||
|
public long getCreationTime() {
|
||
|
return creationTime;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the representation of the state that causes this rule to become active.
|
||
|
*/
|
||
|
public void setConditionId(Uri conditionId) {
|
||
|
this.conditionId = getTrimmedUri(conditionId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the interruption filter that is applied when this rule is active.
|
||
|
* @param interruptionFilter The do not disturb mode to enter when this rule is active.
|
||
|
*/
|
||
|
public void setInterruptionFilter(@InterruptionFilter int interruptionFilter) {
|
||
|
this.interruptionFilter = interruptionFilter;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the name of this rule.
|
||
|
*/
|
||
|
public void setName(String name) {
|
||
|
this.name = getTrimmedString(name);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enables this rule.
|
||
|
*/
|
||
|
public void setEnabled(boolean enabled) {
|
||
|
this.enabled = enabled;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets modified state of this rule.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void setModified(boolean modified) {
|
||
|
this.mModified = modified;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the zen policy.
|
||
|
*
|
||
|
* <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule},
|
||
|
* a {@code null} value here means the previous policy is retained.
|
||
|
*/
|
||
|
public void setZenPolicy(@Nullable ZenPolicy zenPolicy) {
|
||
|
this.mZenPolicy = (zenPolicy == null ? null : zenPolicy.copy());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the {@link ZenDeviceEffects} associated to this rule. Device effects specify changes to
|
||
|
* the device behavior that should apply while the rule is active, but are not directly related
|
||
|
* to suppressing notifications (for example: disabling always-on display).
|
||
|
*
|
||
|
* <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule},
|
||
|
* a {@code null} value here means the previous set of effects is retained.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public void setDeviceEffects(@Nullable ZenDeviceEffects deviceEffects) {
|
||
|
mDeviceEffects = deviceEffects;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the configuration activity - an activity that handles
|
||
|
* {@link NotificationManager#ACTION_AUTOMATIC_ZEN_RULE} that shows the user more information
|
||
|
* about this rule and/or allows them to configure it. This is required to be non-null for rules
|
||
|
* that are not backed by a {@link android.service.notification.ConditionProviderService}.
|
||
|
*
|
||
|
* <p>This is exclusive with the {@code owner} supplied in the constructor; rules where a
|
||
|
* configuration activity is set will not use the
|
||
|
* {@link android.service.notification.ConditionProviderService} supplied there to determine
|
||
|
* whether the rule should be active.
|
||
|
*/
|
||
|
public void setConfigurationActivity(@Nullable ComponentName componentName) {
|
||
|
this.configurationActivity = getTrimmedComponentName(componentName);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public void setPackageName(String pkgName) {
|
||
|
mPkg = pkgName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public String getPackageName() {
|
||
|
return mPkg;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the type of the rule.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public @Type int getType() {
|
||
|
return mType;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the type of the rule.
|
||
|
* @hide
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public void setType(@Type int type) {
|
||
|
mType = checkValidType(type);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the user visible description of when this rule is active
|
||
|
* (see {@link Condition#STATE_TRUE}).
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public @Nullable String getTriggerDescription() {
|
||
|
return mTriggerDescription;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets a user visible description of when this rule will be active
|
||
|
* (see {@link Condition#STATE_TRUE}).
|
||
|
*
|
||
|
* A description should be a (localized) string like "Mon-Fri, 9pm-7am" or
|
||
|
* "When connected to [Car Name]".
|
||
|
* @hide
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public void setTriggerDescription(@Nullable String triggerDescription) {
|
||
|
mTriggerDescription = triggerDescription;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the resource id of the drawable icon for this rule.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public @DrawableRes int getIconResId() {
|
||
|
return mIconResId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets a resource id of a tintable vector drawable representing the rule in image form.
|
||
|
* @hide
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public void setIconResId(int iconResId) {
|
||
|
mIconResId = iconResId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets whether this rule can be manually activated by the user even when the triggering
|
||
|
* condition for the rule is not met.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public boolean isManualInvocationAllowed() {
|
||
|
return mAllowManualInvocation;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets whether this rule can be manually activated by the user even when the triggering
|
||
|
* condition for the rule is not met.
|
||
|
* @hide
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public void setManualInvocationAllowed(boolean allowManualInvocation) {
|
||
|
mAllowManualInvocation = allowManualInvocation;
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public void validate() {
|
||
|
if (Flags.modesApi()) {
|
||
|
checkValidType(mType);
|
||
|
if (mDeviceEffects != null) {
|
||
|
mDeviceEffects.validate();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
@Type
|
||
|
private static int checkValidType(@Type int type) {
|
||
|
checkArgument(type >= TYPE_UNKNOWN && type <= TYPE_MANAGED,
|
||
|
"Rule type must be one of TYPE_UNKNOWN, TYPE_OTHER, TYPE_SCHEDULE_TIME, "
|
||
|
+ "TYPE_SCHEDULE_CALENDAR, TYPE_BEDTIME, TYPE_DRIVING, TYPE_IMMERSIVE, "
|
||
|
+ "TYPE_THEATER, or TYPE_MANAGED");
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel dest, int flags) {
|
||
|
dest.writeInt(enabled ? ENABLED : DISABLED);
|
||
|
if (name != null) {
|
||
|
dest.writeInt(1);
|
||
|
dest.writeString(name);
|
||
|
} else {
|
||
|
dest.writeInt(0);
|
||
|
}
|
||
|
dest.writeInt(interruptionFilter);
|
||
|
dest.writeParcelable(conditionId, 0);
|
||
|
dest.writeParcelable(owner, 0);
|
||
|
dest.writeParcelable(configurationActivity, 0);
|
||
|
dest.writeLong(creationTime);
|
||
|
dest.writeParcelable(mZenPolicy, 0);
|
||
|
dest.writeInt(mModified ? ENABLED : DISABLED);
|
||
|
dest.writeString(mPkg);
|
||
|
if (Flags.modesApi()) {
|
||
|
dest.writeParcelable(mDeviceEffects, 0);
|
||
|
dest.writeBoolean(mAllowManualInvocation);
|
||
|
dest.writeInt(mIconResId);
|
||
|
dest.writeString(mTriggerDescription);
|
||
|
dest.writeInt(mType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
StringBuilder sb = new StringBuilder(AutomaticZenRule.class.getSimpleName()).append('[')
|
||
|
.append("enabled=").append(enabled)
|
||
|
.append(",name=").append(name)
|
||
|
.append(",interruptionFilter=").append(interruptionFilter)
|
||
|
.append(",pkg=").append(mPkg)
|
||
|
.append(",conditionId=").append(conditionId)
|
||
|
.append(",owner=").append(owner)
|
||
|
.append(",configActivity=").append(configurationActivity)
|
||
|
.append(",creationTime=").append(creationTime)
|
||
|
.append(",mZenPolicy=").append(mZenPolicy);
|
||
|
|
||
|
if (Flags.modesApi()) {
|
||
|
sb.append(",deviceEffects=").append(mDeviceEffects)
|
||
|
.append(",allowManualInvocation=").append(mAllowManualInvocation)
|
||
|
.append(",iconResId=").append(mIconResId)
|
||
|
.append(",triggerDescription=").append(mTriggerDescription)
|
||
|
.append(",type=").append(mType);
|
||
|
}
|
||
|
|
||
|
return sb.append(']').toString();
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public static String fieldsToString(@ModifiableField int bitmask) {
|
||
|
ArrayList<String> modified = new ArrayList<>();
|
||
|
if ((bitmask & FIELD_NAME) != 0) {
|
||
|
modified.add("FIELD_NAME");
|
||
|
}
|
||
|
if ((bitmask & FIELD_INTERRUPTION_FILTER) != 0) {
|
||
|
modified.add("FIELD_INTERRUPTION_FILTER");
|
||
|
}
|
||
|
return "{" + String.join(",", modified) + "}";
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object o) {
|
||
|
if (!(o instanceof AutomaticZenRule)) return false;
|
||
|
if (o == this) return true;
|
||
|
final AutomaticZenRule other = (AutomaticZenRule) o;
|
||
|
boolean finalEquals = other.enabled == enabled
|
||
|
&& other.mModified == mModified
|
||
|
&& Objects.equals(other.name, name)
|
||
|
&& other.interruptionFilter == interruptionFilter
|
||
|
&& Objects.equals(other.conditionId, conditionId)
|
||
|
&& Objects.equals(other.owner, owner)
|
||
|
&& Objects.equals(other.mZenPolicy, mZenPolicy)
|
||
|
&& Objects.equals(other.configurationActivity, configurationActivity)
|
||
|
&& Objects.equals(other.mPkg, mPkg)
|
||
|
&& other.creationTime == creationTime;
|
||
|
if (Flags.modesApi()) {
|
||
|
return finalEquals
|
||
|
&& Objects.equals(other.mDeviceEffects, mDeviceEffects)
|
||
|
&& other.mAllowManualInvocation == mAllowManualInvocation
|
||
|
&& other.mIconResId == mIconResId
|
||
|
&& Objects.equals(other.mTriggerDescription, mTriggerDescription)
|
||
|
&& other.mType == mType;
|
||
|
}
|
||
|
return finalEquals;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
if (Flags.modesApi()) {
|
||
|
return Objects.hash(enabled, name, interruptionFilter, conditionId, owner,
|
||
|
configurationActivity, mZenPolicy, mDeviceEffects, mModified, creationTime,
|
||
|
mPkg, mAllowManualInvocation, mIconResId, mTriggerDescription, mType);
|
||
|
}
|
||
|
return Objects.hash(enabled, name, interruptionFilter, conditionId, owner,
|
||
|
configurationActivity, mZenPolicy, mModified, creationTime, mPkg);
|
||
|
}
|
||
|
|
||
|
public static final @android.annotation.NonNull Parcelable.Creator<AutomaticZenRule> CREATOR
|
||
|
= new Parcelable.Creator<AutomaticZenRule>() {
|
||
|
@Override
|
||
|
public AutomaticZenRule createFromParcel(Parcel source) {
|
||
|
return new AutomaticZenRule(source);
|
||
|
}
|
||
|
@Override
|
||
|
public AutomaticZenRule[] newArray(int size) {
|
||
|
return new AutomaticZenRule[size];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* If the package or class name of the provided ComponentName are longer than MAX_STRING_LENGTH,
|
||
|
* return a trimmed version that truncates each of the package and class name at the max length.
|
||
|
*/
|
||
|
private static ComponentName getTrimmedComponentName(ComponentName cn) {
|
||
|
if (cn == null) return null;
|
||
|
return new ComponentName(getTrimmedString(cn.getPackageName()),
|
||
|
getTrimmedString(cn.getClassName()));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
|
||
|
*/
|
||
|
private static String getTrimmedString(String input) {
|
||
|
return getTrimmedString(input, MAX_STRING_LENGTH);
|
||
|
}
|
||
|
|
||
|
private static String getTrimmedString(String input, int length) {
|
||
|
if (input != null && input.length() > length) {
|
||
|
return input.substring(0, length);
|
||
|
}
|
||
|
return input;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a truncated copy of the Uri by trimming the string representation to the maximum
|
||
|
* string length.
|
||
|
*/
|
||
|
private static Uri getTrimmedUri(Uri input) {
|
||
|
if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
|
||
|
return Uri.parse(getTrimmedString(input.toString()));
|
||
|
}
|
||
|
return input;
|
||
|
}
|
||
|
|
||
|
@FlaggedApi(Flags.FLAG_MODES_API)
|
||
|
public static final class Builder {
|
||
|
private String mName;
|
||
|
private ComponentName mOwner;
|
||
|
private Uri mConditionId;
|
||
|
private int mInterruptionFilter = NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
||
|
private boolean mEnabled = true;
|
||
|
private ComponentName mConfigurationActivity = null;
|
||
|
private ZenPolicy mPolicy = null;
|
||
|
private ZenDeviceEffects mDeviceEffects = null;
|
||
|
private int mType = TYPE_UNKNOWN;
|
||
|
private String mDescription;
|
||
|
private int mIconResId;
|
||
|
private boolean mAllowManualInvocation;
|
||
|
private long mCreationTime;
|
||
|
private String mPkg;
|
||
|
|
||
|
public Builder(@NonNull AutomaticZenRule rule) {
|
||
|
mName = rule.getName();
|
||
|
mOwner = rule.getOwner();
|
||
|
mConditionId = rule.getConditionId();
|
||
|
mInterruptionFilter = rule.getInterruptionFilter();
|
||
|
mEnabled = rule.isEnabled();
|
||
|
mConfigurationActivity = rule.getConfigurationActivity();
|
||
|
mPolicy = rule.getZenPolicy();
|
||
|
mDeviceEffects = rule.getDeviceEffects();
|
||
|
mType = rule.getType();
|
||
|
mDescription = rule.getTriggerDescription();
|
||
|
mIconResId = rule.getIconResId();
|
||
|
mAllowManualInvocation = rule.isManualInvocationAllowed();
|
||
|
mCreationTime = rule.getCreationTime();
|
||
|
mPkg = rule.getPackageName();
|
||
|
}
|
||
|
|
||
|
public Builder(@NonNull String name, @NonNull Uri conditionId) {
|
||
|
mName = Objects.requireNonNull(name);
|
||
|
mConditionId = Objects.requireNonNull(conditionId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the name of this rule.
|
||
|
*/
|
||
|
public @NonNull Builder setName(@NonNull String name) {
|
||
|
mName = name;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the component name of the
|
||
|
* {@link android.service.notification.ConditionProviderService} that manages this rule
|
||
|
* (but note that {@link android.service.notification.ConditionProviderService} is
|
||
|
* deprecated in favor of using {@link NotificationManager#setAutomaticZenRuleState} to
|
||
|
* notify the system about the state of your rule).
|
||
|
*
|
||
|
* <p>This is exclusive with {@link #setConfigurationActivity}; rules where a configuration
|
||
|
* activity is set will not use the component set here to determine whether the rule
|
||
|
* should be active.
|
||
|
*/
|
||
|
public @NonNull Builder setOwner(@Nullable ComponentName owner) {
|
||
|
mOwner = owner;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the representation of the state that causes this rule to become active.
|
||
|
*/
|
||
|
public @NonNull Builder setConditionId(@NonNull Uri conditionId) {
|
||
|
mConditionId = conditionId;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the interruption filter that is applied when this rule is active.
|
||
|
*/
|
||
|
public @NonNull Builder setInterruptionFilter(
|
||
|
@InterruptionFilter int interruptionFilter) {
|
||
|
mInterruptionFilter = interruptionFilter;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enables this rule. Rules are enabled by default.
|
||
|
*/
|
||
|
public @NonNull Builder setEnabled(boolean enabled) {
|
||
|
mEnabled = enabled;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the configuration activity - an activity that handles
|
||
|
* {@link NotificationManager#ACTION_AUTOMATIC_ZEN_RULE} that shows the user more
|
||
|
* information about this rule and/or allows them to configure it. This is required to be
|
||
|
* non-null for rules that are not backed by a
|
||
|
* {@link android.service.notification.ConditionProviderService}.
|
||
|
*
|
||
|
* <p>This is exclusive with {@link #setOwner}; rules where a configuration
|
||
|
* activity is set will not use the
|
||
|
* {@link android.service.notification.ConditionProviderService} supplied there to determine
|
||
|
* whether the rule should be active.
|
||
|
*/
|
||
|
public @NonNull Builder setConfigurationActivity(
|
||
|
@Nullable ComponentName configurationActivity) {
|
||
|
mConfigurationActivity = configurationActivity;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the zen policy.
|
||
|
*
|
||
|
* <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule},
|
||
|
* a {@code null} value here means the previous policy is retained.
|
||
|
*/
|
||
|
public @NonNull Builder setZenPolicy(@Nullable ZenPolicy policy) {
|
||
|
mPolicy = policy;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the {@link ZenDeviceEffects} associated to this rule. Device effects specify changes
|
||
|
* to the device behavior that should apply while the rule is active, but are not directly
|
||
|
* related to suppressing notifications (for example: disabling always-on display).
|
||
|
*
|
||
|
* <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule},
|
||
|
* a {@code null} value here means the previous set of effects is retained.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setDeviceEffects(@Nullable ZenDeviceEffects deviceEffects) {
|
||
|
mDeviceEffects = deviceEffects;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the type of the rule.
|
||
|
*/
|
||
|
public @NonNull Builder setType(@Type int type) {
|
||
|
mType = checkValidType(type);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets a user visible description of when this rule will be active
|
||
|
* (see {@link Condition#STATE_TRUE}).
|
||
|
*
|
||
|
* <p>A description should be a (localized) string like "Mon-Fri, 9pm-7am" or
|
||
|
* "When connected to [Car Name]".
|
||
|
*/
|
||
|
public @NonNull Builder setTriggerDescription(@Nullable String description) {
|
||
|
mDescription = description;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets a resource id of a tintable vector drawable representing the rule in image form.
|
||
|
*/
|
||
|
public @NonNull Builder setIconResId(@DrawableRes int iconResId) {
|
||
|
mIconResId = iconResId;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets whether this rule can be manually activated by the user even when the triggering
|
||
|
* condition for the rule is not met.
|
||
|
*/
|
||
|
public @NonNull Builder setManualInvocationAllowed(boolean allowManualInvocation) {
|
||
|
mAllowManualInvocation = allowManualInvocation;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the time at which this rule was created, in milliseconds since epoch
|
||
|
* @hide
|
||
|
*/
|
||
|
public @NonNull Builder setCreationTime(long creationTime) {
|
||
|
mCreationTime = creationTime;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public @NonNull AutomaticZenRule build() {
|
||
|
AutomaticZenRule rule = new AutomaticZenRule(mName, mOwner, mConfigurationActivity,
|
||
|
mConditionId, mPolicy, mInterruptionFilter, mEnabled);
|
||
|
rule.mDeviceEffects = mDeviceEffects;
|
||
|
rule.creationTime = mCreationTime;
|
||
|
rule.mType = mType;
|
||
|
rule.mTriggerDescription = mDescription;
|
||
|
rule.mIconResId = mIconResId;
|
||
|
rule.mAllowManualInvocation = mAllowManualInvocation;
|
||
|
rule.setPackageName(mPkg);
|
||
|
|
||
|
return rule;
|
||
|
}
|
||
|
}
|
||
|
}
|