diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/ProfileTriggerHelper.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/ProfileTriggerHelper.java index 928a719..2e7e4c4 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/ProfileTriggerHelper.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/ProfileTriggerHelper.java @@ -126,7 +126,7 @@ public class ProfileTriggerHelper extends BroadcastReceiver { private void checkTriggers(int type, String id, int newState) { for (Profile p : mManagerService.getProfileList()) { - if (newState != p.getTrigger(type, id)) { + if (newState != p.getTriggerState(type, id)) { continue; } diff --git a/src/java/cyanogenmod/app/Profile.aidl b/src/java/cyanogenmod/app/Profile.aidl index e211a58..ff6c54e 100644 --- a/src/java/cyanogenmod/app/Profile.aidl +++ b/src/java/cyanogenmod/app/Profile.aidl @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 The CyanogenMod Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/java/cyanogenmod/app/Profile.java b/src/java/cyanogenmod/app/Profile.java index c0bb440..e05ff2a 100755 --- a/src/java/cyanogenmod/app/Profile.java +++ b/src/java/cyanogenmod/app/Profile.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The CyanogenMod Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,6 @@ package cyanogenmod.app; -import android.app.AirplaneModeSettings; -import android.app.BrightnessSettings; -import android.app.ConnectionSettings; -import android.app.RingModeSettings; -import android.app.StreamSettings; import android.content.Context; import android.media.AudioManager; import android.os.Parcel; @@ -31,6 +26,12 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Log; +import cyanogenmod.profiles.AirplaneModeSettings; +import cyanogenmod.profiles.BrightnessSettings; +import cyanogenmod.profiles.ConnectionSettings; +import cyanogenmod.profiles.RingModeSettings; +import cyanogenmod.profiles.StreamSettings; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -44,7 +45,11 @@ import java.util.Map.Entry; import java.util.UUID; /** - * @hide + * A class that represents a device profile. + * + * A {@link Profile} can serve a multitude of purposes, allowing the creator(user) + * to set overrides for streams, triggers, screen lock, brightness, various other + * settings. */ public final class Profile implements Parcelable, Comparable { @@ -68,10 +73,6 @@ public final class Profile implements Parcelable, Comparable { private int mProfileType; - private static final int CONDITIONAL_TYPE = 1; - - private static final int TOGGLE_TYPE = 0; - private Map streams = new HashMap(); private Map mTriggers = new HashMap(); @@ -90,48 +91,96 @@ public final class Profile implements Parcelable, Comparable { private int mDozeMode = DozeMode.DEFAULT; - /** @hide */ + /** + * Lock modes of a device + */ public static class LockMode { + /** Represents a default state lock mode (user choice) */ public static final int DEFAULT = 0; + /** Represents an insecure state lock mode, where the device has no security screen */ public static final int INSECURE = 1; + /** Represents a disabled state lock mode, where the devices lock screen can be removed */ public static final int DISABLE = 2; } - /** @hide */ + /** + * Expanded desktop modes available on a device + */ public static class ExpandedDesktopMode { + /** Represents a default state expanded desktop mode (user choice) */ public static final int DEFAULT = 0; + /** Represents an enabled expanded desktop mode */ public static final int ENABLE = 1; + /** Represents a disabled expanded desktop mode */ public static final int DISABLE = 2; } - /** @hide */ + /** + * Doze modes available on a device + */ public static class DozeMode { + /** Represents a default Doze mode (user choice) */ public static final int DEFAULT = 0; + /** Represents an enabled Doze mode */ public static final int ENABLE = 1; + /** Represents an disabled Doze mode */ public static final int DISABLE = 2; } - /** @hide */ + /** + * Available trigger types on the device, usually hardware + */ public static class TriggerType { + /** Represents a WiFi trigger type */ public static final int WIFI = 0; + /** Represents a Bluetooth trigger type */ public static final int BLUETOOTH = 1; } - /** @hide */ + /** + * Various trigger states associated with a {@link TriggerType} + */ public static class TriggerState { + /** A {@link TriggerState) for when the {@link TriggerType} connects */ public static final int ON_CONNECT = 0; + /** A {@link TriggerState) for when the {@link TriggerType} disconnects */ public static final int ON_DISCONNECT = 1; + /** A {@link TriggerState) for when the {@link TriggerType} is disabled */ public static final int DISABLED = 2; + /** + * A {@link TriggerState) for when the {@link TriggerType#BLUETOOTH} + * connects for A2DP session + */ public static final int ON_A2DP_CONNECT = 3; + /** + * A {@link TriggerState) for when the {@link TriggerType#BLUETOOTH} + * disconnects from A2DP session + */ public static final int ON_A2DP_DISCONNECT = 4; } + /** + * A {@link Profile} type + */ + public static class Type { + /** Profile type which represents a toggle {@link Profile} */ + public static final int TOGGLE = 0; + /** Profile type which represents a conditional {@link Profile} */ + public static final int CONDITIONAL = 1; + } + + /** + * A {@link ProfileTrigger} is a {@link TriggerType} which can be queried from the OS + */ public static class ProfileTrigger implements Parcelable { private int mType; private String mId; private String mName; private int mState; + /** + * @hide + */ public ProfileTrigger(int type, String id, int state, String name) { mType = type; mId = id; @@ -159,22 +208,41 @@ public final class Profile implements Parcelable, Comparable { return 0; } + /** + * Get the {@link ProfileTrigger} {@link TriggerType} + * @return {@link TriggerType} + */ public int getType() { return mType; } + /** + * Get the name associated with the {@link ProfileTrigger} + * @return a string name + */ public String getName() { return mName; } + /** + * Get the id associated with the {@link ProfileTrigger} + * @return an string identifier + */ public String getId() { return mId; } + /** + * Get the state associated with the {@link ProfileTrigger} + * @return an integer indicating the state + */ public int getState() { return mState; } + /** + * @hide + */ public void getXmlString(StringBuilder builder, Context context) { final String itemType = mType == TriggerType.WIFI ? "wifiAP" : "btDevice"; @@ -193,6 +261,9 @@ public final class Profile implements Parcelable, Comparable { builder.append(">\n"); } + /** + * @hide + */ public static ProfileTrigger fromXml(XmlPullParser xpp, Context context) { final String name = xpp.getName(); final int type; @@ -219,6 +290,9 @@ public final class Profile implements Parcelable, Comparable { return type == TriggerType.WIFI ? "ssid" : "address"; } + /** + * @hide + */ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public ProfileTrigger createFromParcel(Parcel in) { @@ -244,16 +318,16 @@ public final class Profile implements Parcelable, Comparable { } }; - /** @hide */ public Profile(String name) { this(name, -1, UUID.randomUUID()); } - private Profile(String name, int nameResId, UUID uuid) { + /** @hide */ + public Profile(String name, int nameResId, UUID uuid) { mName = name; mNameResId = nameResId; mUuid = uuid; - mProfileType = TOGGLE_TYPE; //Default to toggle type + mProfileType = Type.TOGGLE; //Default to toggle type mDirty = false; } @@ -261,7 +335,13 @@ public final class Profile implements Parcelable, Comparable { readFromParcel(in); } - public int getTrigger(int type, String id) { + /** + * Get the {@link TriggerState} for a {@link ProfileTrigger} with a given id + * @param type {@link TriggerType} + * @param id string id of {@link ProfileTrigger} + * @return {@link TriggerState} + */ + public int getTriggerState(int type, String id) { ProfileTrigger trigger = id != null ? mTriggers.get(id) : null; if (trigger != null) { return trigger.mState; @@ -269,6 +349,11 @@ public final class Profile implements Parcelable, Comparable { return TriggerState.DISABLED; } + /** + * Get all the {@link ProfileTrigger}s for a given {@link TriggerType} + * @param type {@link TriggerType} + * @return an array list of {@link ProfileTrigger}s + */ public ArrayList getTriggersFromType(int type) { ArrayList result = new ArrayList(); for (Entry profileTrigger: mTriggers.entrySet()) { @@ -280,6 +365,10 @@ public final class Profile implements Parcelable, Comparable { return result; } + /** + * Set a custom {@link ProfileTrigger} + * @hide + */ public void setTrigger(int type, String id, int state, String name) { if (id == null || type < TriggerType.WIFI || type > TriggerType.BLUETOOTH @@ -302,6 +391,14 @@ public final class Profile implements Parcelable, Comparable { mDirty = true; } + /** + * Set a {@link ProfileTrigger} on the {@link Profile} + * @param trigger a {@link ProfileTrigger} + */ + public void setTrigger(ProfileTrigger trigger) { + setTrigger(trigger.getType(), trigger.getId(), trigger.getState(), trigger.getName()); + } + public int compareTo(Object obj) { Profile tmp = (Profile) obj; if (mName.compareTo(tmp.mName) < 0) { @@ -312,20 +409,26 @@ public final class Profile implements Parcelable, Comparable { return 0; } - /** @hide */ - public void addProfileGroup(ProfileGroup value) { - if (value.isDefaultGroup()) { + /** + * Add a {@link ProfileGroup} to the {@link Profile} + * @param profileGroup + */ + public void addProfileGroup(ProfileGroup profileGroup) { + if (profileGroup.isDefaultGroup()) { /* we must not have more than one default group */ if (mDefaultGroup != null) { return; } - mDefaultGroup = value; + mDefaultGroup = profileGroup; } - profileGroups.put(value.getUuid(), value); + profileGroups.put(profileGroup.getUuid(), profileGroup); mDirty = true; } - /** @hide */ + /** + * Remove a {@link ProfileGroup} with a given {@link UUID} + * @param uuid + */ public void removeProfileGroup(UUID uuid) { if (!profileGroups.get(uuid).isDefaultGroup()) { profileGroups.remove(uuid); @@ -334,14 +437,27 @@ public final class Profile implements Parcelable, Comparable { } } + /** + * Get {@link ProfileGroup}s associated with the {@link Profile} + * @return {@link ProfileGroup[]} + */ public ProfileGroup[] getProfileGroups() { return profileGroups.values().toArray(new ProfileGroup[profileGroups.size()]); } + /** + * Get a {@link ProfileGroup} with a given {@link UUID} + * @param uuid + * @return a {@link ProfileGroup} + */ public ProfileGroup getProfileGroup(UUID uuid) { return profileGroups.get(uuid); } + /** + * Get the default {@link ProfileGroup} associated with the {@link Profile} + * @return the default {@link ProfileGroup} + */ public ProfileGroup getDefaultGroup() { return mDefaultGroup; } @@ -417,36 +533,62 @@ public final class Profile implements Parcelable, Comparable { mDozeMode = in.readInt(); } + /** + * Get the name associated with the {@link Profile} + * @return a string name of the profile + */ public String getName() { return mName; } - /** @hide */ + /** + * Set a name for the {@link Profile} + * @param name a string for the {@link Profile} + */ public void setName(String name) { mName = name; mNameResId = -1; mDirty = true; } + /** + * Get the {@link Type} of the {@link Profile} + * @return + */ public int getProfileType() { return mProfileType; } - /** @hide */ + /** + * Set the {@link Type} for the {@link Profile} + * @param type a type of profile + */ public void setProfileType(int type) { mProfileType = type; mDirty = true; } + /** + * Get the {@link UUID} associated with the {@link Profile} + * @return the uuid for the profile + */ public UUID getUuid() { if (this.mUuid == null) this.mUuid = UUID.randomUUID(); return this.mUuid; } + /** + * Get the secondary {@link UUID}s for the {@link Profile} + * @return the secondary uuids for the Profile + */ public UUID[] getSecondaryUuids() { return mSecondaryUuids.toArray(new UUID[mSecondaryUuids.size()]); } + /** + * Set a list of secondary {@link UUID}s for the {@link Profile} + * @param uuids + */ public void setSecondaryUuids(List uuids) { mSecondaryUuids.clear(); if (uuids != null) { @@ -455,6 +597,10 @@ public final class Profile implements Parcelable, Comparable { } } + /** + * Add a secondary {@link UUID} to the {@link Profile} + * @param uuid + */ public void addSecondaryUuid(UUID uuid) { if (uuid != null) { mSecondaryUuids.add(uuid); @@ -462,37 +608,66 @@ public final class Profile implements Parcelable, Comparable { } } + /** + * @hide + */ public boolean getStatusBarIndicator() { return mStatusBarIndicator; } + /** + * @hide + */ public void setStatusBarIndicator(boolean newStatusBarIndicator) { mStatusBarIndicator = newStatusBarIndicator; mDirty = true; } + /** + * Check if the given {@link Profile} is a {@link Type#CONDITIONAL} + * @return true if conditional + */ public boolean isConditionalType() { - return(mProfileType == CONDITIONAL_TYPE ? true : false); + return(mProfileType == Type.CONDITIONAL ? true : false); } + /** + * @hide + */ public void setConditionalType() { - mProfileType = CONDITIONAL_TYPE; + mProfileType = Type.CONDITIONAL; mDirty = true; } + /** + * Get the {@link RingModeSettings} for the {@link Profile} + * @return + */ public RingModeSettings getRingMode() { return mRingMode; } + /** + * Set the {@link RingModeSettings} for the {@link Profile} + * @param descriptor + */ public void setRingMode(RingModeSettings descriptor) { mRingMode = descriptor; mDirty = true; } + /** + * Get the {@link LockMode} for the {@link Profile} + * @return + */ public int getScreenLockMode() { return mScreenLockMode; } + /** + * Set the {@link LockMode} for the {@link Profile} + * @param screenLockMode + */ public void setScreenLockMode(int screenLockMode) { if (screenLockMode < LockMode.DEFAULT || screenLockMode > LockMode.DISABLE) { mScreenLockMode = LockMode.DEFAULT; @@ -502,10 +677,18 @@ public final class Profile implements Parcelable, Comparable { mDirty = true; } + /** + * Get the {@link ExpandedDesktopMode} for the {@link Profile} + * @return + */ public int getExpandedDesktopMode() { return mExpandedDesktopMode; } + /** + * Set the {@link ExpandedDesktopMode} for the {@link Profile} + * @return + */ public void setExpandedDesktopMode(int expandedDesktopMode) { if (expandedDesktopMode < ExpandedDesktopMode.DEFAULT || expandedDesktopMode > ExpandedDesktopMode.DISABLE) { @@ -516,10 +699,18 @@ public final class Profile implements Parcelable, Comparable { mDirty = true; } + /** + * Get the {@link DozeMode} associated with the {@link Profile} + * @return + */ public int getDozeMode() { return mDozeMode; } + /** + * Set the {@link DozeMode} associated with the {@link Profile} + * @return + */ public void setDozeMode(int dozeMode) { if (dozeMode < DozeMode.DEFAULT || dozeMode > DozeMode.DISABLE) { @@ -530,19 +721,35 @@ public final class Profile implements Parcelable, Comparable { mDirty = true; } + /** + * Get the {@link AirplaneModeSettings} associated with the {@link Profile} + * @return + */ public AirplaneModeSettings getAirplaneMode() { return mAirplaneMode; } + /** + * Set the {@link AirplaneModeSettings} associated with the {@link Profile} + * @param descriptor + */ public void setAirplaneMode(AirplaneModeSettings descriptor) { mAirplaneMode = descriptor; mDirty = true; } + /** + * Get the {@link BrightnessSettings} associated with the {@link Profile} + * @return + */ public BrightnessSettings getBrightness() { return mBrightness; } + /** + * Set the {@link BrightnessSettings} associated with the {@link Profile} + * @return + */ public void setBrightness(BrightnessSettings descriptor) { mBrightness = descriptor; mDirty = true; @@ -603,7 +810,7 @@ public final class Profile implements Parcelable, Comparable { builder.append("\n"); builder.append(""); - builder.append(getProfileType() == TOGGLE_TYPE ? "toggle" : "conditional"); + builder.append(getProfileType() == Type.TOGGLE ? "toggle" : "conditional"); builder.append("\n"); builder.append(""); @@ -746,7 +953,7 @@ public final class Profile implements Parcelable, Comparable { } if (name.equals("profiletype")) { profile.setProfileType(xpp.nextText().equals("toggle") - ? TOGGLE_TYPE : CONDITIONAL_TYPE); + ? Type.TOGGLE : Type.CONDITIONAL); } if (name.equals("ringModeDescriptor")) { RingModeSettings smd = RingModeSettings.fromXml(xpp, context); @@ -836,35 +1043,52 @@ public final class Profile implements Parcelable, Comparable { } } - /** @hide */ + /** + * Get the settings for a stream id in the {@link Profile} + * @return {@link StreamSettings} + */ public StreamSettings getSettingsForStream(int streamId){ return streams.get(streamId); } - /** @hide */ + /** + * Set the {@link StreamSettings} for the {@link Profile} + * @param descriptor + */ public void setStreamSettings(StreamSettings descriptor){ streams.put(descriptor.getStreamId(), descriptor); mDirty = true; } - /** @hide */ + /** + * Get the {@link StreamSettings} for the {@link Profile} + * @return {@link Collection} + */ public Collection getStreamSettings(){ return streams.values(); } - /** @hide */ + /** + * Get the settings for a connection id in the {@link Profile} + * @return {@link ConnectionSettings} + */ public ConnectionSettings getSettingsForConnection(int connectionId){ return connections.get(connectionId); } - /** @hide */ + /** + * Set the {@link ConnectionSettings} for the {@link Profile} + * @param descriptor + */ public void setConnectionSettings(ConnectionSettings descriptor){ connections.put(descriptor.getConnectionId(), descriptor); } - /** @hide */ + /** + * Get the {@link ConnectionSettings} for the {@link Profile} + * @return {@link Collection} + */ public Collection getConnectionSettings(){ return connections.values(); } - } diff --git a/src/java/cyanogenmod/app/ProfileGroup.java b/src/java/cyanogenmod/app/ProfileGroup.java index 2a0c6fb..3403172 100644 --- a/src/java/cyanogenmod/app/ProfileGroup.java +++ b/src/java/cyanogenmod/app/ProfileGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The CyanogenMod Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import java.util.UUID; /** * @hide + * TODO: This isn't ready for public use */ public final class ProfileGroup implements Parcelable { private static final String TAG = "ProfileGroup"; diff --git a/src/java/cyanogenmod/app/ProfileManager.java b/src/java/cyanogenmod/app/ProfileManager.java index 30ae1d7..a662665 100644 --- a/src/java/cyanogenmod/app/ProfileManager.java +++ b/src/java/cyanogenmod/app/ProfileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The CyanogenMod Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.NotificationGroup; import android.content.Context; -import android.os.Handler; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; @@ -36,7 +35,26 @@ import com.android.internal.R; /** - * @hide + *

+ * The ProfileManager allows you to create {@link Profile}s and {@link ProfileGroup}s to create + * specific behavior states depending on triggers from hardware devices changing states, such as: + * + * WiFi being enabled + * WiFi connecting to a certain AP + * Bluetooth connecting to a certain device + * Bluetooth disconnecting to a certain device + * NFC tag being scanned + * + * Depending on these triggers, you can override connection settings, lockscreen modes, media + * stream volumes and various other settings. + *

+ * + * To get the instance of this class, utilize ProfileManager#getInstance(Context context) + * + * This manager requires the android.permission.WRITE_SETTINGS permission. + * + * @see cyanogenmod.app.Profile + * @see cyanogenmod.app.ProfileGroup */ public class ProfileManager { @@ -51,49 +69,43 @@ public class ProfileManager { /** *

Broadcast Action: A new profile has been selected. This can be triggered by the user * or by calls to the ProfileManagerService / Profile.

- * @hide */ public static final String INTENT_ACTION_PROFILE_SELECTED = - "android.intent.action.PROFILE_SELECTED"; + "cyanogenmod.platform.intent.action.PROFILE_SELECTED"; /** - * Extra for {@link INTENT_ACTION_PROFILE_SELECTED} and {@link INTENT_ACTION_PROFILE_UPDATED}: + *

Broadcast Action: Current profile has been updated. This is triggered every time the + * currently active profile is updated, instead of selected.

+ *

For instance, this includes profile updates caused by a locale change, which doesn't + * trigger a profile selection, but causes its name to change.

+ */ + public static final String INTENT_ACTION_PROFILE_UPDATED = + "cyanogenmod.platform.intent.action.PROFILE_UPDATED"; + + /** + * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED} and {@link #INTENT_ACTION_PROFILE_UPDATED}: * The name of the newly activated or updated profile - * @hide */ public static final String EXTRA_PROFILE_NAME = "name"; /** - * Extra for {@link INTENT_ACTION_PROFILE_SELECTED} and {@link INTENT_ACTION_PROFILE_UPDATED}: + * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED} and {@link #INTENT_ACTION_PROFILE_UPDATED}: * The string representation of the UUID of the newly activated or updated profile - * @hide */ public static final String EXTRA_PROFILE_UUID = "uuid"; /** - * Extra for {@link INTENT_ACTION_PROFILE_SELECTED}: + * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED}: * The name of the previously active profile - * @hide */ public static final String EXTRA_LAST_PROFILE_NAME = "lastName"; /** - * Extra for {@link INTENT_ACTION_PROFILE_SELECTED}: + * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED}: * The string representation of the UUID of the previously active profile - * @hide */ public static final String EXTRA_LAST_PROFILE_UUID = "uuid"; - /** - *

Broadcast Action: Current profile has been updated. This is triggered every time the - * currently active profile is updated, instead of selected.

- *

For instance, this includes profile updates caused by a locale change, which doesn't - * trigger a profile selection, but causes its name to change.

- * @hide - */ - public static final String INTENT_ACTION_PROFILE_UPDATED = - "android.intent.action.PROFILE_UPDATED"; - /** * Activity Action: Shows a profile picker. *

@@ -101,13 +113,13 @@ public class ProfileManager { * {@link #EXTRA_PROFILE_TITLE}. *

* Output: {@link #EXTRA_PROFILE_PICKED_UUID}. - * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_PROFILE_PICKER = "android.intent.action.PROFILE_PICKER"; + public static final String ACTION_PROFILE_PICKER = + "cyanogenmod_platform.intent.action.PROFILE_PICKER"; /** - * @hide + * Constant for NO_PROFILE */ public static final UUID NO_PROFILE = UUID.fromString("00000000-0000-0000-0000-000000000000"); @@ -118,7 +130,6 @@ public class ProfileManager { * {@link #EXTRA_PROFILE_PICKED_UUID} will be {@link #NO_PROFILE}. * * @see #ACTION_PROFILE_PICKER - * @hide */ public static final String EXTRA_PROFILE_SHOW_NONE = "android.intent.extra.profile.SHOW_NONE"; @@ -127,11 +138,10 @@ public class ProfileManager { * Given to the profile picker as a {@link UUID} string representation. The {@link UUID} * representation of the current profile, which will be used to show a checkmark next to * the item for this {@link UUID}. If the item is {@link #NO_PROFILE} then "None" item - * is selected if {@link EXTRA_PROFILE_SHOW_NONE} is enabled. Otherwise, the current + * is selected if {@link #EXTRA_PROFILE_SHOW_NONE} is enabled. Otherwise, the current * profile is selected. * * @see #ACTION_PROFILE_PICKER - * @hide */ public static final String EXTRA_PROFILE_EXISTING_UUID = "android.intent.extra.profile.EXISTING_UUID"; @@ -142,9 +152,9 @@ public class ProfileManager { * in most cases. * * @see #ACTION_PROFILE_PICKER - * @hide */ - public static final String EXTRA_PROFILE_TITLE = "android.intent.extra.profile.TITLE"; + public static final String EXTRA_PROFILE_TITLE = + "cyanogenmod.platform.intent.extra.profile.TITLE"; /** * Returned from the profile picker as a {@link UUID} string representation. @@ -154,29 +164,26 @@ public class ProfileManager { *

  • null if the "None" item was picked. * * @see #ACTION_PROFILE_PICKER - * @hide */ public static final String EXTRA_PROFILE_PICKED_UUID = - "android.intent.extra.profile.PICKED_UUID"; - + "cyanogenmod.platform.intent.extra.profile.PICKED_UUID"; /** * Broadcast intent action indicating that Profiles has been enabled or disabled. * One extra provides this state as an int. * * @see #EXTRA_PROFILES_STATE - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String PROFILES_STATE_CHANGED_ACTION = - "android.app.profiles.PROFILES_STATE_CHANGED"; + "cyanogenmod.platform.app.profiles.PROFILES_STATE_CHANGED"; + /** * The lookup key for an int that indicates whether Profiles are enabled or * disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #PROFILES_STATE_DISABLED * @see #PROFILES_STATE_ENABLED - * @hide */ public static final String EXTRA_PROFILES_STATE = "profile_state"; @@ -185,23 +192,21 @@ public class ProfileManager { * The default theme is com.android.internal.R.Theme_Holo_Dialog_Alert. * * @see #ACTION_PROFILE_PICKER - * @hide */ public static final String EXTRA_PROFILE_DIALOG_THEME = - "android.intent.extra.profile.DIALOG_THEME"; + "cyanogenmod.platform.intent.extra.profile.DIALOG_THEME"; /** * Profiles are disabled. * * @see #PROFILES_STATE_CHANGED_ACTION - * @hide */ public static final int PROFILES_STATE_DISABLED = 0; + /** * Profiles are enabled. * * @see #PROFILES_STATE_CHANGED_ACTION - * @hide */ public static final int PROFILES_STATE_ENABLED = 1; @@ -223,7 +228,7 @@ public class ProfileManager { /** * Get or create an instance of the {@link cyanogenmod.app.ProfileManager} * @param context - * @return {@link cyanogenmod.app.ProfileManager} + * @return {@link ProfileManager} */ public static ProfileManager getInstance(Context context) { if (sProfileManagerInstance == null) { @@ -255,6 +260,10 @@ public class ProfileManager { } } + /** + * Set the active {@link Profile} by {@link UUID} + * @param profileUuid the {@link UUID} associated with the profile + */ public void setActiveProfile(UUID profileUuid) { if (Settings.System.getInt(mContext.getContentResolver(), SYSTEM_PROFILES_ENABLED, 1) == 1) { @@ -267,6 +276,10 @@ public class ProfileManager { } } + /** + * Get the active {@link Profile} + * @return active {@link Profile} + */ public Profile getActiveProfile() { if (Settings.System.getInt(mContext.getContentResolver(), SYSTEM_PROFILES_ENABLED, 1) == 1) { @@ -285,7 +298,10 @@ public class ProfileManager { } - /** @hide */ + /** + * Add a {@link Profile} that can be selected by the user + * @param profile a {@link Profile} object + */ public void addProfile(Profile profile) { try { getService().addProfile(profile); @@ -294,7 +310,10 @@ public class ProfileManager { } } - /** @hide */ + /** + * Remove a {@link Profile} from user selection + * @param profile a {@link Profile} object + */ public void removeProfile(Profile profile) { try { getService().removeProfile(profile); @@ -303,7 +322,10 @@ public class ProfileManager { } } - /** @hide */ + /** + * Update a {@link Profile} object + * @param profile a {@link Profile} object + */ public void updateProfile(Profile profile) { try { getService().updateProfile(profile); @@ -312,6 +334,11 @@ public class ProfileManager { } } + /** + * Get the {@link Profile} object by its literal name + * @param profileName name associated with the profile + * @return profile a {@link Profile} object + */ @Deprecated public Profile getProfile(String profileName) { try { @@ -322,6 +349,11 @@ public class ProfileManager { return null; } + /** + * Get a {@link Profile} via {@link UUID} + * @param profileUuid {@link UUID} associated with the profile + * @return {@link Profile} + */ public Profile getProfile(UUID profileUuid) { try { return getService().getProfile(new ParcelUuid(profileUuid)); @@ -331,6 +363,10 @@ public class ProfileManager { return null; } + /** + * Get the profile names currently available to the user + * @return {@link String[]} of profile names + */ public String[] getProfileNames() { try { Profile[] profiles = getService().getProfiles(); @@ -345,6 +381,10 @@ public class ProfileManager { return null; } + /** + * Get the {@link Profile}s currently available to the user + * @return {@link Profile[]} + */ public Profile[] getProfiles() { try { return getService().getProfiles(); @@ -354,6 +394,11 @@ public class ProfileManager { return null; } + /** + * Check if a {@link Profile} exists via its literal name + * @param profileName a profile name + * @return whether or not the profile exists + */ public boolean profileExists(String profileName) { try { return getService().profileExistsByName(profileName); @@ -365,6 +410,11 @@ public class ProfileManager { } } + /** + * Check if a {@link Profile} exists via its {@link UUID} + * @param profileUuid the profiles {@link UUID} + * @return whether or not the profile exists + */ public boolean profileExists(UUID profileUuid) { try { return getService().profileExists(new ParcelUuid(profileUuid)); @@ -376,6 +426,12 @@ public class ProfileManager { } } + /** + * Check if a NotificationGroup exists + * @param notificationGroupName the name of the notification group + * @return whether or not the notification group exists + * @hide + */ public boolean notificationGroupExists(String notificationGroupName) { try { return getService().notificationGroupExistsByName(notificationGroupName); @@ -387,7 +443,11 @@ public class ProfileManager { } } - /** @hide */ + /** + * Get the currently available NotificationGroups + * @return NotificationGroup + * @hide + */ public NotificationGroup[] getNotificationGroups() { try { return getService().getNotificationGroups(); @@ -397,7 +457,11 @@ public class ProfileManager { return null; } - /** @hide */ + /** + * Add a NotificationGroup to the available list + * @param group NotificationGroup + * @hide + */ public void addNotificationGroup(NotificationGroup group) { try { getService().addNotificationGroup(group); @@ -406,7 +470,11 @@ public class ProfileManager { } } - /** @hide */ + /** + * Remove a NotificationGroup from the available list + * @param group NotificationGroup + * @hide + */ public void removeNotificationGroup(NotificationGroup group) { try { getService().removeNotificationGroup(group); @@ -415,7 +483,11 @@ public class ProfileManager { } } - /** @hide */ + /** + * Update a NotificationGroup from the available list + * @param group NotificationGroup + * @hide + */ public void updateNotificationGroup(NotificationGroup group) { try { getService().updateNotificationGroup(group); @@ -424,7 +496,11 @@ public class ProfileManager { } } - /** @hide */ + /** + * Get a NotificationGroup for a specific package + * @param pkg name of the package + * @hide + */ public NotificationGroup getNotificationGroupForPackage(String pkg) { try { return getService().getNotificationGroupForPackage(pkg); @@ -434,7 +510,11 @@ public class ProfileManager { return null; } - /** @hide */ + /** + * Get a NotificationGroup from the available list via {@link UUID} + * @param uuid {@link UUID} of the notification group + * @hide + */ public NotificationGroup getNotificationGroup(UUID uuid) { try { return getService().getNotificationGroup(new ParcelUuid(uuid)); @@ -444,7 +524,11 @@ public class ProfileManager { return null; } - /** @hide */ + /** + * Get an active {@link ProfileGroup} via its package name + * @param packageName the package name associated to the profile group + * @return {@link ProfileGroup} + */ public ProfileGroup getActiveProfileGroup(String packageName) { NotificationGroup notificationGroup = getNotificationGroupForPackage(packageName); if (notificationGroup == null) { @@ -454,7 +538,9 @@ public class ProfileManager { return getActiveProfile().getProfileGroup(notificationGroup.getUuid()); } - /** @hide */ + /** + * Reset all profiles, groups, and notification groups to default state + */ public void resetAll() { try { getService().resetAll(); diff --git a/src/java/cyanogenmod/profiles/AirplaneModeSettings.java b/src/java/cyanogenmod/profiles/AirplaneModeSettings.java new file mode 100644 index 0000000..125cb4d --- /dev/null +++ b/src/java/cyanogenmod/profiles/AirplaneModeSettings.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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 cyanogenmod.profiles; + +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + + +import java.io.IOException; + +/** + * The {@link AirplaneModeSettings} class allows for overriding and setting the airplane mode. + * + *

    Example for setting the airplane mode to enabled: + *

    + * AirplaneModeSettings airplaneMode = new AirplaneModeSettings(63, true)
    + * profile.setBrightnessSettings(twentyFivePercent);
    + * 
    + */ +public final class AirplaneModeSettings implements Parcelable { + + private int mValue; + private boolean mOverride; + private boolean mDirty; + + /** @hide */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public AirplaneModeSettings createFromParcel(Parcel in) { + return new AirplaneModeSettings(in); + } + + @Override + public AirplaneModeSettings[] newArray(int size) { + return new AirplaneModeSettings[size]; + } + }; + + /** + * BooleanStates for specific {@link AirplaneModeSettings} + */ + public static class BooleanState { + /** Disabled state */ + public static final int STATE_DISALED = 0; + /** Enabled state */ + public static final int STATE_ENABLED = 1; + } + + /** + * Unwrap {@link AirplaneModeSettings} from a parcel. + * @param parcel + */ + public AirplaneModeSettings(Parcel parcel) { + readFromParcel(parcel); + } + + /** + * Construct a {@link AirplaneModeSettings} with a default value of + * {@link BooleanState#STATE_DISALED}. + */ + public AirplaneModeSettings() { + this(BooleanState.STATE_DISALED, false); + } + + /** + * Construct a {@link AirplaneModeSettings} with a default value and whether or not it should + * override user settings. + * @param value ex: {@link BooleanState#STATE_DISALED} + * @param override whether or not the setting should override user settings + */ + public AirplaneModeSettings(int value, boolean override) { + mValue = value; + mOverride = override; + mDirty = false; + } + + /** + * Get the default value for the {@link AirplaneModeSettings} + * @return integer value corresponding with its brightness value + */ + public int getValue() { + return mValue; + } + + /** + * Set the default value for the {@link AirplaneModeSettings} + * @param value {@link BooleanState#STATE_DISALED} + */ + public void setValue(int value) { + mValue = value; + mDirty = true; + } + + /** + * Set whether or not the {@link AirplaneModeSettings} should override default user values + * @param override boolean override + */ + public void setOverride(boolean override) { + mOverride = override; + mDirty = true; + } + + /** + * Check whether or not the {@link AirplaneModeSettings} overrides user settings. + * @return true if override + */ + public boolean isOverride() { + return mOverride; + } + + /** @hide */ + public boolean isDirty() { + return mDirty; + } + + /** @hide */ + public void processOverride(Context context) { + if (isOverride()) { + int current = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0); + if (current != mValue) { + Settings.Global.putInt(context.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, mValue); + Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + intent.putExtra("state", mValue == 1); + context.sendBroadcast(intent); + } + } + } + + /** @hide */ + public static AirplaneModeSettings fromXml(XmlPullParser xpp, Context context) + throws XmlPullParserException, IOException { + int event = xpp.next(); + AirplaneModeSettings airplaneModeDescriptor = new AirplaneModeSettings(); + while ((event != XmlPullParser.END_TAG && event != XmlPullParser.END_DOCUMENT) || + !xpp.getName().equals("airplaneModeDescriptor")) { + if (event == XmlPullParser.START_TAG) { + String name = xpp.getName(); + if (name.equals("value")) { + airplaneModeDescriptor.mValue = Integer.parseInt(xpp.nextText()); + } else if (name.equals("override")) { + airplaneModeDescriptor.mOverride = Boolean.parseBoolean(xpp.nextText()); + } + } else if (event == XmlPullParser.END_DOCUMENT) { + throw new IOException("Premature end of file while parsing airplane mode settings"); + } + event = xpp.next(); + } + return airplaneModeDescriptor; + } + + /** @hide */ + public void getXmlString(StringBuilder builder, Context context) { + builder.append("\n"); + builder.append(mValue); + builder.append("\n"); + builder.append(mOverride); + builder.append("\n\n"); + } + + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mOverride ? 1 : 0); + dest.writeInt(mValue); + dest.writeInt(mDirty ? 1 : 0); + } + + /** @hide */ + public void readFromParcel(Parcel in) { + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } +} diff --git a/src/java/cyanogenmod/profiles/BrightnessSettings.java b/src/java/cyanogenmod/profiles/BrightnessSettings.java new file mode 100644 index 0000000..8be956b --- /dev/null +++ b/src/java/cyanogenmod/profiles/BrightnessSettings.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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 cyanogenmod.profiles; + +import android.content.Context; +import android.provider.Settings; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + + +import java.io.IOException; + +/** + * The {@link BrightnessSettings} class allows for overriding and setting the brightness level + * of the display. The range for brightness is between 0 -> 255. + * + *

    Example for setting the brightness to ~25% (255 * .25): + *

    + * BrightnessSettings twentyFivePercent = new BrightnessSettings(63, true)
    + * profile.setBrightnessSettings(twentyFivePercent);
    + * 
    + */ +public final class BrightnessSettings implements Parcelable { + + private int mValue; + private boolean mOverride; + private boolean mDirty; + + /** @hide */ + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public BrightnessSettings createFromParcel(Parcel in) { + return new BrightnessSettings(in); + } + + @Override + public BrightnessSettings[] newArray(int size) { + return new BrightnessSettings[size]; + } + }; + + /** + * Unwrap {@link BrightnessSettings} from a parcel. + * @param parcel + */ + public BrightnessSettings(Parcel parcel) { + readFromParcel(parcel); + } + + /** + * Construct a {@link BrightnessSettings} with a default value of 0. + */ + public BrightnessSettings() { + this(0, false); + } + + /** + * Construct a {@link BrightnessSettings} with a default value and whether or not it should + * override user settings. + * @param value ex: 255 (MAX) + * @param override whether or not the setting should override user settings + */ + public BrightnessSettings(int value, boolean override) { + mValue = value; + mOverride = override; + mDirty = false; + } + + /** + * Get the default value for the {@link BrightnessSettings} + * @return integer value corresponding with its brightness value + */ + public int getValue() { + return mValue; + } + + /** + * Set the default value for the {@link BrightnessSettings} + * @param value ex: 255 (MAX) + */ + public void setValue(int value) { + mValue = value; + mDirty = true; + } + + /** + * Set whether or not the {@link BrightnessSettings} should override default user values + * @param override boolean override + */ + public void setOverride(boolean override) { + mOverride = override; + mDirty = true; + } + + /** + * Check whether or not the {@link BrightnessSettings} overrides user settings. + * @return true if override + */ + public boolean isOverride() { + return mOverride; + } + + /** @hide */ + public boolean isDirty() { + return mDirty; + } + + /** @hide */ + public void processOverride(Context context) { + if (isOverride()) { + final boolean automatic = Settings.System.getInt(context.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL) + == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; + if (automatic) { + final float current = Settings.System.getFloat(context.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, -2f); + // Convert from [0, 255] to [-1, 1] for SCREEN_AUTO_BRIGHTNESS_ADJ + final float adj = mValue / (255 / 2f) - 1; + if (current != adj) { + Settings.System.putFloat(context.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj); + } + } else { + final int current = Settings.System.getInt(context.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, -1); + if (current != mValue) { + Settings.System.putInt(context.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, mValue); + } + } + } + } + + /** @hide */ + public static BrightnessSettings fromXml(XmlPullParser xpp, Context context) + throws XmlPullParserException, IOException { + int event = xpp.next(); + BrightnessSettings brightnessDescriptor = new BrightnessSettings(); + while (event != XmlPullParser.END_TAG || !xpp.getName().equals("brightnessDescriptor")) { + if (event == XmlPullParser.START_TAG) { + String name = xpp.getName(); + if (name.equals("value")) { + brightnessDescriptor.mValue = Integer.parseInt(xpp.nextText()); + } else if (name.equals("override")) { + brightnessDescriptor.mOverride = Boolean.parseBoolean(xpp.nextText()); + } + } + event = xpp.next(); + } + return brightnessDescriptor; + } + + /** @hide */ + public void getXmlString(StringBuilder builder, Context context) { + builder.append("\n"); + builder.append(mValue); + builder.append("\n"); + builder.append(mOverride); + builder.append("\n\n"); + } + + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mOverride ? 1 : 0); + dest.writeInt(mValue); + dest.writeInt(mDirty ? 1 : 0); + } + + /** @hide */ + public void readFromParcel(Parcel in) { + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } +} diff --git a/src/java/cyanogenmod/profiles/ConnectionSettings.java b/src/java/cyanogenmod/profiles/ConnectionSettings.java new file mode 100644 index 0000000..9f4b24f --- /dev/null +++ b/src/java/cyanogenmod/profiles/ConnectionSettings.java @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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 cyanogenmod.profiles; + +import android.bluetooth.BluetoothAdapter; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.location.LocationManager; +import android.net.wifi.WifiManager; +import android.net.wimax.WimaxHelper; +import android.nfc.NfcAdapter; +import android.os.Parcel; +import android.os.Parcelable; +import android.provider.Settings; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import com.android.internal.telephony.RILConstants; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * The {@link ConnectionSettings} class allows for creating Network/Hardware overrides + * depending on their capabilities. + * + *

    Example for enabling/disabling sync settings: + *

    + * ConnectionSettings connectionSettings =
    + *         new ConnectionSettings(ConnectionSettings.PROFILE_CONNECTION_SYNC,
    + *         shouldBeEnabled() ?
    + *         {@link BooleanState#STATE_ENABLED} : {@link BooleanState#STATE_DISALED},
    + *         true)
    + * profile.setConnectionSettings(connectionSettings);
    + * 
    + */ +public final class ConnectionSettings implements Parcelable { + + private int mConnectionId; + private int mValue; + private boolean mOverride; + private boolean mDirty; + + /** + * The #PROFILE_CONNECTION_MOBILEDATA allows for enabling and disabling the mobile + * data connection. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_MOBILEDATA = 0; + + /** + * The #PROFILE_CONNECTION_WIFI allows for enabling and disabling the WiFi connection + * on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_WIFI = 1; + + /** + * The #PROFILE_CONNECTION_WIFIAP allows for enabling and disabling the WiFi hotspot + * on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_WIFIAP = 2; + + /** + * The #PROFILE_CONNECTION_WIMAX allows for enabling and disabling the WIMAX radio (if exists) + * on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_WIMAX = 3; + + /** + * The #PROFILE_CONNECTION_GPS allows for enabling and disabling the GPS radio (if exists) + * on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_GPS = 4; + + /** + * The #PROFILE_CONNECTION_SYNC allows for enabling and disabling the global sync state + * on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_SYNC = 5; + + /** + * The #PROFILE_CONNECTION_BLUETOOTH allows for enabling and disabling the Bluetooth device + * (if exists) on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_BLUETOOTH = 7; + + /** + * The #PROFILE_CONNECTION_NFS allows for enabling and disabling the NFC device + * (if exists) on the device. Boolean connection settings {@link BooleanState} + */ + public static final int PROFILE_CONNECTION_NFC = 8; + + /** + * The #PROFILE_CONNECTION_2G3G4G allows for flipping between 2G/3G/4G (if exists) + * on the device. + */ + public static final int PROFILE_CONNECTION_2G3G4G = 9; + + // retrieved from Phone.apk + private static final String ACTION_MODIFY_NETWORK_MODE = + "com.android.internal.telephony.MODIFY_NETWORK_MODE"; + private static final String EXTRA_NETWORK_MODE = "networkMode"; + + /** + * BooleanStates for specific {@link ConnectionSettings} + */ + public static class BooleanState { + /** Disabled state */ + public static final int STATE_DISALED = 0; + /** Enabled state */ + public static final int STATE_ENABLED = 1; + } + + private static final int CM_MODE_2G = 0; + private static final int CM_MODE_3G = 1; + private static final int CM_MODE_4G = 2; + private static final int CM_MODE_2G3G = 3; + private static final int CM_MODE_ALL = 4; + + /** @hide */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public ConnectionSettings createFromParcel(Parcel in) { + return new ConnectionSettings(in); + } + + @Override + public ConnectionSettings[] newArray(int size) { + return new ConnectionSettings[size]; + } + }; + + /** + * Unwrap {@link ConnectionSettings} from a parcel. + * @param parcel + */ + public ConnectionSettings(Parcel parcel) { + readFromParcel(parcel); + } + + /** + * Construct a {@link ConnectionSettings} with a connection id and default states. + * @param connectionId ex: #PROFILE_CONNECTION_NFC + */ + public ConnectionSettings(int connectionId) { + this(connectionId, 0, false); + } + + /** + * Construct a {@link ConnectionSettings} with a connection id, default value + * {@see BooleanState}, and if the setting should override the user defaults. + * @param connectionId an identifier for the ConnectionSettings (ex:#PROFILE_CONNECTION_WIFI) + * @param value default value for the ConnectionSettings (ex:{@link BooleanState#STATE_ENABLED}) + * @param override whether or not the {@link ConnectionSettings} should override user defaults + */ + public ConnectionSettings(int connectionId, int value, boolean override) { + mConnectionId = connectionId; + mValue = value; + mOverride = override; + mDirty = false; + } + + /** + * Retrieve the connection id associated with the {@link ConnectionSettings} + * @return an integer identifier + */ + public int getConnectionId() { + return mConnectionId; + } + + /** + * Get the default value for the {@link ConnectionSettings} + * @return integer value corresponding with its state + */ + public int getValue() { + return mValue; + } + + /** + * Set the default value for the {@link ConnectionSettings} + * @param value {@link BooleanState} + */ + public void setValue(int value) { + mValue = value; + mDirty = true; + } + + /** + * Set whether or not the {@link ConnectionSettings} should override default user values + * @param override boolean override + */ + public void setOverride(boolean override) { + mOverride = override; + mDirty = true; + } + + /** + * Check whether or not the {@link ConnectionSettings} overrides user settings. + * @return true if override + */ + public boolean isOverride() { + return mOverride; + } + + /** @hide */ + public boolean isDirty() { + return mDirty; + } + + /** @hide */ + public void processOverride(Context context) { + BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter(); + LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + TelephonyManager tm = (TelephonyManager) + context.getSystemService(Context.TELEPHONY_SERVICE); + NfcAdapter nfcAdapter = null; + try { + nfcAdapter = NfcAdapter.getNfcAdapter(context); + } catch (UnsupportedOperationException e) { + //Nfc not available + } + + boolean forcedState = getValue() == 1; + boolean currentState; + + switch (getConnectionId()) { + case PROFILE_CONNECTION_MOBILEDATA: + currentState = tm.getDataEnabled(); + if (forcedState != currentState) { + int phoneCount = tm.getPhoneCount(); + for (int i = 0; i < phoneCount; i++) { + Settings.Global.putInt(context.getContentResolver(), + Settings.Global.MOBILE_DATA + i, (forcedState) ? 1 : 0); + int[] subId = SubscriptionManager.getSubId(i); + tm.setDataEnabled(subId[0], forcedState); + } + } + break; + case PROFILE_CONNECTION_2G3G4G: + Intent intent = new Intent(ACTION_MODIFY_NETWORK_MODE); + switch(getValue()) { + case CM_MODE_2G: + intent.putExtra(EXTRA_NETWORK_MODE, RILConstants.NETWORK_MODE_GSM_ONLY); + break; + case CM_MODE_3G: + intent.putExtra(EXTRA_NETWORK_MODE, RILConstants.NETWORK_MODE_WCDMA_ONLY); + break; + case CM_MODE_4G: + intent.putExtra(EXTRA_NETWORK_MODE, RILConstants.NETWORK_MODE_LTE_ONLY); + break; + case CM_MODE_2G3G: + intent.putExtra(EXTRA_NETWORK_MODE, RILConstants.NETWORK_MODE_WCDMA_PREF); + break; + case CM_MODE_ALL: + intent.putExtra(EXTRA_NETWORK_MODE, + RILConstants.NETWORK_MODE_LTE_GSM_WCDMA); + break; + default: + return; + } + context.sendBroadcast(intent); + break; + case PROFILE_CONNECTION_BLUETOOTH: + int btstate = bta.getState(); + if (forcedState && (btstate == BluetoothAdapter.STATE_OFF + || btstate == BluetoothAdapter.STATE_TURNING_OFF)) { + bta.enable(); + } else if (!forcedState && (btstate == BluetoothAdapter.STATE_ON + || btstate == BluetoothAdapter.STATE_TURNING_ON)) { + bta.disable(); + } + break; + case PROFILE_CONNECTION_GPS: + currentState = lm.isProviderEnabled(LocationManager.GPS_PROVIDER); + if (currentState != forcedState) { + Settings.Secure.setLocationProviderEnabled(context.getContentResolver(), + LocationManager.GPS_PROVIDER, forcedState); + } + break; + case PROFILE_CONNECTION_SYNC: + currentState = ContentResolver.getMasterSyncAutomatically(); + if (forcedState != currentState) { + ContentResolver.setMasterSyncAutomatically(forcedState); + } + break; + case PROFILE_CONNECTION_WIFI: + int wifiApState = wm.getWifiApState(); + currentState = wm.isWifiEnabled(); + if (currentState != forcedState) { + // Disable wifi tether + if (forcedState && (wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) || + (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED)) { + wm.setWifiApEnabled(null, false); + } + wm.setWifiEnabled(forcedState); + } + break; + case PROFILE_CONNECTION_WIFIAP: + int wifiState = wm.getWifiState(); + currentState = wm.isWifiApEnabled(); + if (currentState != forcedState) { + // Disable wifi + if (forcedState && (wifiState == WifiManager.WIFI_STATE_ENABLING) || + (wifiState == WifiManager.WIFI_STATE_ENABLED)) { + wm.setWifiEnabled(false); + } + wm.setWifiApEnabled(null, forcedState); + } + break; + case PROFILE_CONNECTION_WIMAX: + if (WimaxHelper.isWimaxSupported(context)) { + currentState = WimaxHelper.isWimaxEnabled(context); + if (currentState != forcedState) { + WimaxHelper.setWimaxEnabled(context, forcedState); + } + } + break; + case PROFILE_CONNECTION_NFC: + if (nfcAdapter != null) { + int adapterState = nfcAdapter.getAdapterState(); + currentState = (adapterState == NfcAdapter.STATE_ON || + adapterState == NfcAdapter.STATE_TURNING_ON); + if (currentState != forcedState) { + if (forcedState) { + nfcAdapter.enable(); + } else if (!forcedState && adapterState != NfcAdapter.STATE_TURNING_OFF) { + nfcAdapter.disable(); + } + } + } + break; + } + } + + /** @hide */ + public static ConnectionSettings fromXml(XmlPullParser xpp, Context context) + throws XmlPullParserException, IOException { + int event = xpp.next(); + ConnectionSettings connectionDescriptor = new ConnectionSettings(0); + while (event != XmlPullParser.END_TAG || !xpp.getName().equals("connectionDescriptor")) { + if (event == XmlPullParser.START_TAG) { + String name = xpp.getName(); + if (name.equals("connectionId")) { + connectionDescriptor.mConnectionId = Integer.parseInt(xpp.nextText()); + } else if (name.equals("value")) { + connectionDescriptor.mValue = Integer.parseInt(xpp.nextText()); + } else if (name.equals("override")) { + connectionDescriptor.mOverride = Boolean.parseBoolean(xpp.nextText()); + } + } else if (event == XmlPullParser.END_DOCUMENT) { + throw new IOException("Premature end of file while parsing connection settings"); + } + event = xpp.next(); + } + return connectionDescriptor; + } + + /** @hide */ + public void getXmlString(StringBuilder builder, Context context) { + builder.append("\n"); + builder.append(mConnectionId); + builder.append("\n"); + builder.append(mValue); + builder.append("\n"); + builder.append(mOverride); + builder.append("\n\n"); + } + + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mConnectionId); + dest.writeInt(mOverride ? 1 : 0); + dest.writeInt(mValue); + dest.writeInt(mDirty ? 1 : 0); + } + + /** @hide */ + public void readFromParcel(Parcel in) { + mConnectionId = in.readInt(); + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } +} diff --git a/src/java/cyanogenmod/profiles/RingModeSettings.java b/src/java/cyanogenmod/profiles/RingModeSettings.java new file mode 100644 index 0000000..abca360 --- /dev/null +++ b/src/java/cyanogenmod/profiles/RingModeSettings.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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 cyanogenmod.profiles; + +import android.content.Context; +import android.media.AudioManager; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * The {@link StreamSettings} class allows for creating various {@link android.media.AudioManager} + * overrides on the device depending on their capabilities. + * + *

    Example for setting the default ring mode to muted: + *

    + * RingModeSettings ringSettings = new RingModeSettings(RING_MODE_MUTE, true));
    + * profile.setRingModeSettings(ringSettings);
    + * 
    + */ +public final class RingModeSettings implements Parcelable { + public static final String RING_MODE_NORMAL = "normal"; + public static final String RING_MODE_VIBRATE = "vibrate"; + public static final String RING_MODE_MUTE = "mute"; + + private String mValue; + private boolean mOverride; + private boolean mDirty; + + /** @hide */ + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public RingModeSettings createFromParcel(Parcel in) { + return new RingModeSettings(in); + } + + @Override + public RingModeSettings[] newArray(int size) { + return new RingModeSettings[size]; + } + }; + + /** + * Unwrap {@link RingModeSettings} from a parcel. + * @param parcel + */ + public RingModeSettings(Parcel parcel) { + readFromParcel(parcel); + } + + /** + * Construct a {@link RingModeSettings} with a default state of #RING_MODE_NORMAL. + */ + public RingModeSettings() { + this(RING_MODE_NORMAL, false); + } + + /** + * Construct a {@link RingModeSettings} with a default value and whether or not it should + * override user settings. + * @param value ex: #RING_MODE_VIBRATE + * @param override whether or not the setting should override user settings + */ + public RingModeSettings(String value, boolean override) { + mValue = value; + mOverride = override; + mDirty = false; + } + + /** + * Get the default value for the {@link RingModeSettings} + * @return integer value corresponding with its type + */ + public String getValue() { + return mValue; + } + + /** + * Set the default value for the {@link RingModeSettings} + * @param value ex: #RING_MODE_VIBRATE + */ + public void setValue(String value) { + mValue = value; + mDirty = true; + } + + /** + * Set whether or not the {@link RingModeSettings} should override default user values + * @param override boolean override + */ + public void setOverride(boolean override) { + mOverride = override; + mDirty = true; + } + + /** + * Check whether or not the {@link RingModeSettings} overrides user settings. + * @return true if override + */ + public boolean isOverride() { + return mOverride; + } + + /** @hide */ + public boolean isDirty() { + return mDirty; + } + + /** @hide */ + public void processOverride(Context context) { + if (isOverride()) { + int ringerMode = AudioManager.RINGER_MODE_NORMAL; + if (mValue.equals(RING_MODE_MUTE)) { + ringerMode = AudioManager.RINGER_MODE_SILENT; + } else if (mValue.equals(RING_MODE_VIBRATE)) { + ringerMode = AudioManager.RINGER_MODE_VIBRATE; + } + AudioManager amgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + amgr.setRingerModeInternal(ringerMode); + } + } + + /** @hide */ + public static RingModeSettings fromXml(XmlPullParser xpp, Context context) + throws XmlPullParserException, IOException { + int event = xpp.next(); + RingModeSettings ringModeDescriptor = new RingModeSettings(); + while ((event != XmlPullParser.END_TAG && event != XmlPullParser.END_DOCUMENT) || + !xpp.getName().equals("ringModeDescriptor")) { + if (event == XmlPullParser.START_TAG) { + String name = xpp.getName(); + if (name.equals("value")) { + ringModeDescriptor.mValue = xpp.nextText(); + } else if (name.equals("override")) { + ringModeDescriptor.mOverride = Boolean.parseBoolean(xpp.nextText()); + } + } else if (event == XmlPullParser.END_DOCUMENT) { + throw new IOException("Premature end of file while parsing ring mode settings"); + } + event = xpp.next(); + } + return ringModeDescriptor; + } + + /** @hide */ + public void getXmlString(StringBuilder builder, Context context) { + builder.append("\n"); + builder.append(mValue); + builder.append("\n"); + builder.append(mOverride); + builder.append("\n\n"); + } + + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mOverride ? 1 : 0); + dest.writeString(mValue); + dest.writeInt(mDirty ? 1 : 0); + } + + /** @hide */ + public void readFromParcel(Parcel in) { + mOverride = in.readInt() != 0; + mValue = in.readString(); + mDirty = in.readInt() != 0; + } +} diff --git a/src/java/cyanogenmod/profiles/StreamSettings.java b/src/java/cyanogenmod/profiles/StreamSettings.java new file mode 100644 index 0000000..9898334 --- /dev/null +++ b/src/java/cyanogenmod/profiles/StreamSettings.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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 cyanogenmod.profiles; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.IOException; + +/** + * The {@link StreamSettings} class allows for creating various {@link android.media.AudioManager} + * overrides on the device depending on their capabilities. + * + *

    Example for setting the alarm stream defaults and override: + *

    + * StreamSettings alarmStreamSettings = new StreamSettings(AudioManager.STREAM_ALARM,
    + *         am.getStreamVolume(AudioManager.STREAM_ALARM), true));
    + * profile.setStreamSettings(alarmStreamSettings);
    + * 
    + */ +public final class StreamSettings implements Parcelable{ + + private int mStreamId; + private int mValue; + private boolean mOverride; + private boolean mDirty; + + /** @hide */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public StreamSettings createFromParcel(Parcel in) { + return new StreamSettings(in); + } + + @Override + public StreamSettings[] newArray(int size) { + return new StreamSettings[size]; + } + }; + + /** + * Unwrap {@link StreamSettings} from a parcel. + * @param parcel + */ + public StreamSettings(Parcel parcel) { + readFromParcel(parcel); + } + + /** + * Construct a {@link StreamSettings} with a stream id and default states. + * @param streamId ex: {@link android.media.AudioManager#STREAM_ALARM} + */ + public StreamSettings(int streamId) { + this(streamId, 0, false); + } + + /** + * Construct a {@link StreamSettings} with a stream id, default value, + * and if the setting should override the user defaults. + * @param streamId ex: {@link android.media.AudioManager#STREAM_ALARM} + * @param value default value for the {@link StreamSettings} + * @param override whether or not the {@link StreamSettings} should override user defaults + */ + public StreamSettings(int streamId, int value, boolean override) { + mStreamId = streamId; + mValue = value; + mOverride = override; + mDirty = false; + } + + /** + * Retrieve the stream id id associated with the {@link StreamSettings} + * @return an integer identifier + */ + public int getStreamId() { + return mStreamId; + } + + /** + * Get the default value for the {@link StreamSettings} + * @return integer value corresponding with its state + */ + public int getValue() { + return mValue; + } + + /** + * Set the default value for the {@link StreamSettings} + * @param value see {@link android.media.AudioManager} for viable values + */ + public void setValue(int value) { + mValue = value; + mDirty = true; + } + + /** + * Set whether or not the {@link StreamSettings} should override default user values + * @param override boolean override + */ + public void setOverride(boolean override) { + mOverride = override; + mDirty = true; + } + + /** + * Check whether or not the {@link StreamSettings} overrides user settings. + * @return true if override + */ + public boolean isOverride() { + return mOverride; + } + + /** @hide */ + public boolean isDirty() { + return mDirty; + } + + /** @hide */ + public static StreamSettings fromXml(XmlPullParser xpp, Context context) + throws XmlPullParserException, IOException { + int event = xpp.next(); + StreamSettings streamDescriptor = new StreamSettings(0); + while (event != XmlPullParser.END_TAG || !xpp.getName().equals("streamDescriptor")) { + if (event == XmlPullParser.START_TAG) { + String name = xpp.getName(); + if (name.equals("streamId")) { + streamDescriptor.mStreamId = Integer.parseInt(xpp.nextText()); + } else if (name.equals("value")) { + streamDescriptor.mValue = Integer.parseInt(xpp.nextText()); + } else if (name.equals("override")) { + streamDescriptor.mOverride = Boolean.parseBoolean(xpp.nextText()); + } + } else if (event == XmlPullParser.END_DOCUMENT) { + throw new IOException("Premature end of file while parsing stream settings"); + } + event = xpp.next(); + } + return streamDescriptor; + } + + /** @hide */ + public void getXmlString(StringBuilder builder, Context context) { + builder.append("\n"); + builder.append(mStreamId); + builder.append("\n"); + builder.append(mValue); + builder.append("\n"); + builder.append(mOverride); + builder.append("\n\n"); + mDirty = false; + } + + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mStreamId); + dest.writeInt(mOverride ? 1 : 0); + dest.writeInt(mValue); + dest.writeInt(mDirty ? 1 : 0); + } + + /** @hide */ + public void readFromParcel(Parcel in) { + mStreamId = in.readInt(); + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } +} diff --git a/tests/Android.mk b/tests/Android.mk index c6d67b5..db67c3a 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -28,4 +28,4 @@ LOCAL_CERTIFICATE := platform LOCAL_PROGUARD_ENABLED := disabled -include $(BUILD_PACKAGE) \ No newline at end of file +include $(BUILD_PACKAGE) diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 029f4fc..e58f59f 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -5,6 +5,7 @@ android:versionName="1.0"> + + + + + + + diff --git a/tests/src/org/cyanogenmod/tests/profiles/ProfileTest.java b/tests/src/org/cyanogenmod/tests/profiles/ProfileTest.java new file mode 100644 index 0000000..a7705df --- /dev/null +++ b/tests/src/org/cyanogenmod/tests/profiles/ProfileTest.java @@ -0,0 +1,76 @@ +package org.cyanogenmod.tests.profiles; + +import android.os.Bundle; + +import cyanogenmod.app.Profile; +import cyanogenmod.app.Profile.Type; + +import cyanogenmod.app.ProfileManager; +import org.cyanogenmod.tests.TestActivity; + +import java.util.UUID; + +/** + * Created by adnan on 6/26/15. + */ +public class ProfileTest extends TestActivity { + private ProfileManager mProfileManager; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mProfileManager = ProfileManager.getInstance(this); + } + + @Override + protected Test[] tests() { + return mTests; + } + + @Override + protected String tag() { + return null; + } + + private Test[] mTests = new Test[] { + new Test("test create random Profile") { + public void run() { + Profile profile = new Profile("Test Profile"); + profile.setProfileType(Type.TOGGLE); + profile.setExpandedDesktopMode(Profile.ExpandedDesktopMode.ENABLE); + profile.setDozeMode(Profile.DozeMode.DEFAULT); + profile.setScreenLockMode(Profile.LockMode.DISABLE); + mProfileManager.addProfile(profile); + } + }, + new Test("test add static Profile") { + public void run() { + Profile profile = new Profile("Test Profile-Active", + 0, UUID.fromString("65cd0d0c-1c42-11e5-9a21-1697f925ec7b")); + profile.setProfileType(Type.TOGGLE); + profile.setExpandedDesktopMode(Profile.ExpandedDesktopMode.ENABLE); + profile.setDozeMode(Profile.DozeMode.DEFAULT); + profile.setScreenLockMode(Profile.LockMode.DISABLE); + mProfileManager.addProfile(profile); + mProfileManager.setActiveProfile(profile.getUuid()); + } + }, + new Test("test remove static Profile") { + public void run() { + mProfileManager.removeProfile( + mProfileManager.getProfile("65cd0d0c-1c42-11e5-9a21-1697f925ec7b")); + } + }, + new Test("test create Profile and Set Active") { + public void run() { + Profile profile = new Profile("Test Profile-Active"); + profile.setProfileType(Type.TOGGLE); + profile.setExpandedDesktopMode(Profile.ExpandedDesktopMode.ENABLE); + profile.setDozeMode(Profile.DozeMode.DEFAULT); + profile.setScreenLockMode(Profile.LockMode.DISABLE); + mProfileManager.addProfile(profile); + mProfileManager.setActiveProfile(profile.getUuid()); + } + }, + }; +}