Merge "Remove activitystrings.xml from localized resource directories"
diff --git a/api/current.txt b/api/current.txt
index 2eea8ac..7ebabe4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -382,6 +382,7 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
+ field public static final int colorAccent = 16843842; // 0x1010442
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
@@ -397,6 +398,9 @@
field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
field public static final int colorPressedHighlight = 16843661; // 0x101038d
+ field public static final int colorPrimary = 16843840; // 0x1010440
+ field public static final int colorPrimaryDark = 16843841; // 0x1010441
+ field public static final int colorPrimaryLight = 16843839; // 0x101043f
field public static final int columnCount = 16843639; // 0x1010377
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -1650,7 +1654,10 @@
field public static final int decelerate_cubic = 17563651; // 0x10c0003
field public static final int decelerate_quad = 17563649; // 0x10c0001
field public static final int decelerate_quint = 17563653; // 0x10c0005
+ field public static final int fast_out_linear_in = 17563663; // 0x10c000f
+ field public static final int fast_out_slow_in = 17563661; // 0x10c000d
field public static final int linear = 17563659; // 0x10c000b
+ field public static final int linear_out_slow_in = 17563662; // 0x10c000e
field public static final int overshoot = 17563656; // 0x10c0008
}
@@ -6464,6 +6471,7 @@
field public static final java.lang.String ALARM_SERVICE = "alarm";
field public static final java.lang.String APP_OPS_SERVICE = "appops";
field public static final java.lang.String AUDIO_SERVICE = "audio";
+ field public static final java.lang.String BATTERY_SERVICE = "batterymanager";
field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
field public static final int BIND_ADJUST_WITH_ACTIVITY = 128; // 0x80
field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
@@ -15808,10 +15816,13 @@
public final class NsdServiceInfo implements android.os.Parcelable {
ctor public NsdServiceInfo();
method public int describeContents();
+ method public java.util.Map<java.lang.String, byte[]> getAttributes();
method public java.net.InetAddress getHost();
method public int getPort();
method public java.lang.String getServiceName();
method public java.lang.String getServiceType();
+ method public void removeAttribute(java.lang.String);
+ method public void setAttribute(java.lang.String, java.lang.String);
method public void setHost(java.net.InetAddress);
method public void setPort(int);
method public void setServiceName(java.lang.String);
@@ -18971,6 +18982,7 @@
public class BatteryManager {
ctor public BatteryManager();
+ method public android.os.BatteryProperty getProperty(int) throws android.os.RemoteException;
field public static final int BATTERY_HEALTH_COLD = 7; // 0x7
field public static final int BATTERY_HEALTH_DEAD = 4; // 0x4
field public static final int BATTERY_HEALTH_GOOD = 2; // 0x2
@@ -18998,6 +19010,18 @@
field public static final java.lang.String EXTRA_VOLTAGE = "voltage";
}
+ public class BatteryProperty implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getInt();
+ method public void readFromParcel(android.os.Parcel);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CAPACITY = 4; // 0x4
+ field public static final int CHARGE_COUNTER = 1; // 0x1
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final int CURRENT_AVERAGE = 3; // 0x3
+ field public static final int CURRENT_NOW = 2; // 0x2
+ }
+
public class Binder implements android.os.IBinder {
ctor public Binder();
method public void attachInterface(android.os.IInterface, java.lang.String);
@@ -23352,6 +23376,67 @@
field public static final java.lang.String TYPE = "type";
}
+ public final class TvContract {
+ method public static final android.net.Uri buildChannelUri(long);
+ method public static final android.net.Uri buildProgramUri(long);
+ field public static final java.lang.String AUTHORITY = "com.android.tv";
+ }
+
+ public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
+ field public static final java.lang.String PACKAGE_NAME = "package_name";
+ }
+
+ public static final class TvContract.Channels implements android.provider.TvContract.BaseTvColumns {
+ field public static final java.lang.String BROWSABLE = "browsable";
+ field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.channels";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DATA = "data";
+ field public static final java.lang.String DESCRIPTION = "description";
+ field public static final java.lang.String DISPLAY_NAME = "display_name";
+ field public static final java.lang.String DISPLAY_NUMBER = "display_number";
+ field public static final java.lang.String SERVICE_NAME = "service_name";
+ field public static final java.lang.String TRANSPORT_STREAM_ID = "transport_stream_id";
+ field public static final java.lang.String TYPE = "type";
+ field public static final int TYPE_1SEG = 263168; // 0x40400
+ field public static final int TYPE_ATSC = 196608; // 0x30000
+ field public static final int TYPE_ATSC_2_0 = 196609; // 0x30001
+ field public static final int TYPE_ATSC_M_H = 196864; // 0x30100
+ field public static final int TYPE_CMMB = 327936; // 0x50100
+ field public static final int TYPE_DTMB = 327680; // 0x50000
+ field public static final int TYPE_DVB_C = 131584; // 0x20200
+ field public static final int TYPE_DVB_C2 = 131585; // 0x20201
+ field public static final int TYPE_DVB_H = 131840; // 0x20300
+ field public static final int TYPE_DVB_S = 131328; // 0x20100
+ field public static final int TYPE_DVB_S2 = 131329; // 0x20101
+ field public static final int TYPE_DVB_SH = 132096; // 0x20400
+ field public static final int TYPE_DVB_T = 131072; // 0x20000
+ field public static final int TYPE_DVB_T2 = 131073; // 0x20001
+ field public static final int TYPE_ISDB_C = 262912; // 0x40300
+ field public static final int TYPE_ISDB_S = 262656; // 0x40200
+ field public static final int TYPE_ISDB_T = 262144; // 0x40000
+ field public static final int TYPE_ISDB_TB = 262400; // 0x40100
+ field public static final int TYPE_OTHER = 0; // 0x0
+ field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
+ field public static final int TYPE_S_DMB = 393472; // 0x60100
+ field public static final int TYPE_T_DMB = 393216; // 0x60000
+ field public static final java.lang.String VERSION_NUMBER = "version_number";
+ }
+
+ public static final class TvContract.Programs implements android.provider.TvContract.BaseTvColumns {
+ field public static final java.lang.String CHANNEL_ID = "channel_id";
+ field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.programs";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DATA = "data";
+ field public static final java.lang.String DESCRIPTION = "description";
+ field public static final java.lang.String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+ field public static final java.lang.String LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+ field public static final java.lang.String TITLE = "title";
+ field public static final java.lang.String VERSION_NUMBER = "version_number";
+ }
+
public class UserDictionary {
ctor public UserDictionary();
field public static final java.lang.String AUTHORITY = "user_dictionary";
@@ -27750,14 +27835,6 @@
method public abstract boolean onTune(android.net.Uri);
}
- public abstract class TvInputSession {
- ctor public TvInputSession();
- method public void release();
- method public void setSurface(android.view.Surface);
- method public void setVolume(float);
- method public void tune(android.net.Uri);
- }
-
}
package android.util {
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index c520b58..859d83b 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -97,7 +97,7 @@
virtual void onExit(int code)
{
- if (mClassName == NULL) {
+ if (mClassName.isEmpty()) {
// if zygote
IPCThreadState::self()->stopProcess();
}
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 466dcd4..948c9a2 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -26,9 +26,17 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.text.TextUtils;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+
/**
* This class is a command line utility for manipulating content. A client
* can insert, update, and remove records in a content provider. For example,
@@ -109,6 +117,12 @@
+ " <METHOD> is the name of a provider-defined method\n"
+ " <ARG> is an optional string argument\n"
+ " <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n"
+ + "\n"
+ + "usage: adb shell content read --uri <URI> [--user <USER_ID>]\n"
+ + " Example:\n"
+ + " # cat default ringtone to a file, then pull to host\n"
+ + " adb shell 'content read --uri content://settings/system/ringtone >"
+ + " /mnt/sdcard/tmp.ogg' && adb pull /mnt/sdcard/tmp.ogg\n"
+ "\n";
private static class Parser {
@@ -117,6 +131,7 @@
private static final String ARGUMENT_UPDATE = "update";
private static final String ARGUMENT_QUERY = "query";
private static final String ARGUMENT_CALL = "call";
+ private static final String ARGUMENT_READ = "read";
private static final String ARGUMENT_WHERE = "--where";
private static final String ARGUMENT_BIND = "--bind";
private static final String ARGUMENT_URI = "--uri";
@@ -154,6 +169,8 @@
return parseQueryCommand();
} else if (ARGUMENT_CALL.equals(operation)) {
return parseCallCommand();
+ } else if (ARGUMENT_READ.equals(operation)) {
+ return parseReadCommand();
} else {
throw new IllegalArgumentException("Unsupported operation: " + operation);
}
@@ -273,6 +290,25 @@
return new CallCommand(uri, userId, method, arg, values);
}
+ private ReadCommand parseReadCommand() {
+ Uri uri = null;
+ int userId = UserHandle.USER_OWNER;
+ for (String argument; (argument = mTokenizer.nextArg())!= null;) {
+ if (ARGUMENT_URI.equals(argument)) {
+ uri = Uri.parse(argumentValueRequired(argument));
+ } else if (ARGUMENT_USER.equals(argument)) {
+ userId = Integer.parseInt(argumentValueRequired(argument));
+ } else {
+ throw new IllegalArgumentException("Unsupported argument: " + argument);
+ }
+ }
+ if (uri == null) {
+ throw new IllegalArgumentException("Content provider URI not specified."
+ + " Did you specify --uri argument?");
+ }
+ return new ReadCommand(uri, userId);
+ }
+
public QueryCommand parseQueryCommand() {
Uri uri = null;
int userId = UserHandle.USER_OWNER;
@@ -458,6 +494,31 @@
}
}
+ private static class ReadCommand extends Command {
+ public ReadCommand(Uri uri, int userId) {
+ super(uri, userId);
+ }
+
+ @Override
+ public void onExecute(IContentProvider provider) throws Exception {
+ final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null);
+ copy(new FileInputStream(fd.getFileDescriptor()), System.out);
+ }
+
+ private static void copy(InputStream is, OutputStream os) throws IOException {
+ final byte[] buffer = new byte[8 * 1024];
+ int read;
+ try {
+ while ((read = is.read(buffer)) > -1) {
+ os.write(buffer, 0, read);
+ }
+ } finally {
+ IoUtils.closeQuietly(is);
+ IoUtils.closeQuietly(os);
+ }
+ }
+ }
+
private static class QueryCommand extends DeleteCommand {
final String[] mProjection;
final String mSortOrder;
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 34b0f3a..9818c33 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -1239,6 +1239,8 @@
public LayoutParams(int width, int height, int gravity) {
super(width, height);
+
+ this.gravity = gravity;
}
public LayoutParams(int gravity) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1c02102..77b5485 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -72,6 +72,7 @@
import android.net.IConnectivityManager;
import android.net.INetworkPolicyManager;
import android.net.NetworkPolicyManager;
+import android.net.NetworkScoreManager;
import android.net.Uri;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
@@ -82,6 +83,7 @@
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.nfc.NfcManager;
+import android.os.BatteryManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -404,6 +406,11 @@
return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName());
}});
+ registerService(BATTERY_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new BatteryManager();
+ }});
+
registerService(NFC_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new NfcManager(ctx);
@@ -648,6 +655,12 @@
ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder);
return new TvInputManager(service, UserHandle.myUserId());
}});
+
+ registerService(NETWORK_SCORE_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new NetworkScoreManager(ctx);
+ }
+ });
}
static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9911467..bb6eeda 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -31,7 +31,7 @@
void enqueueToast(String pkg, ITransientNotification callback, int duration);
void cancelToast(String pkg, ITransientNotification callback);
- void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+ void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
in Notification notification, inout int[] idReceived, int userId);
void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ed0cc23..ff92d82 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2009,6 +2009,7 @@
CAMERA_SERVICE,
PRINT_SERVICE,
MEDIA_SESSION_SERVICE,
+ BATTERY_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -2060,6 +2061,8 @@
* <dd> An {@link android.app.UiModeManager} for controlling UI modes.
* <dt> {@link #DOWNLOAD_SERVICE} ("download")
* <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads
+ * <dt> {@link #BATTERY_SERVICE} ("batterymanager")
+ * <dd> A {@link android.os.BatteryManager} for managing battery state
* </dl>
*
* <p>Note: System services obtained via this API may be closely associated with
@@ -2113,6 +2116,8 @@
* @see android.app.UiModeManager
* @see #DOWNLOAD_SERVICE
* @see android.app.DownloadManager
+ * @see #BATTERY_SERVICE
+ * @see android.os.BatteryManager
*/
public abstract Object getSystemService(@ServiceName @NonNull String name);
@@ -2481,6 +2486,14 @@
/**
* Use with {@link #getSystemService} to retrieve a
+ * {@link android.os.BatteryManager} for managing battery state.
+ *
+ * @see #getSystemService
+ */
+ public static final String BATTERY_SERVICE = "batterymanager";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a
* {@link android.nfc.NfcManager} for using NFC.
*
* @see #getSystemService
@@ -2630,6 +2643,14 @@
public static final String TV_INPUT_SERVICE = "tv_input";
/**
+ * {@link android.net.NetworkScoreManager} for managing network scoring.
+ * @see #getSystemService
+ * @see android.net.NetworkScoreManager
+ * @hide
+ */
+ public static final String NETWORK_SCORE_SERVICE = "network_score";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4b5616f..8d8d220 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3292,19 +3292,23 @@
if (packageName == null || packageName.length() == 0) {
Slog.i(TAG, "verifier package name was null; skipping");
return null;
- } else if (encodedPublicKey == null) {
- Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
}
- PublicKey publicKey = parsePublicKey(encodedPublicKey);
- if (publicKey != null) {
- return new VerifierInfo(packageName, publicKey);
+ final PublicKey publicKey = parsePublicKey(encodedPublicKey);
+ if (publicKey == null) {
+ Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
+ return null;
}
- return null;
+ return new VerifierInfo(packageName, publicKey);
}
- public static final PublicKey parsePublicKey(String encodedPublicKey) {
+ public static final PublicKey parsePublicKey(final String encodedPublicKey) {
+ if (encodedPublicKey == null) {
+ Slog.i(TAG, "Could not parse null public key");
+ return null;
+ }
+
EncodedKeySpec keySpec;
try {
final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 0c0dfe9..b5efa8e 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -857,7 +857,7 @@
* @hide
*/
@Override
- public void vibrate(int owningUid, String owningPackage, long milliseconds,
+ public void vibrate(int uid, String opPkg, long milliseconds,
int streamHint) {
vibrate(new long[] { 0, milliseconds}, -1);
}
@@ -866,7 +866,7 @@
* @hide
*/
@Override
- public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+ public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
int streamHint) {
if (repeat >= pattern.length) {
throw new ArrayIndexOutOfBoundsException();
diff --git a/core/java/android/net/NetworkKey.aidl b/core/java/android/net/NetworkKey.aidl
new file mode 100644
index 0000000..637075f
--- /dev/null
+++ b/core/java/android/net/NetworkKey.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.net;
+
+parcelable NetworkKey;
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
new file mode 100644
index 0000000..cc3ad3e
--- /dev/null
+++ b/core/java/android/net/NetworkKey.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information which identifies a specific network.
+ *
+ * @hide
+ */
+public class NetworkKey implements Parcelable {
+
+ /** A wifi network, for which {@link #wifiKey} will be populated. */
+ public static final int TYPE_WIFI = 1;
+
+ /**
+ * The type of this network.
+ * @see #TYPE_WIFI
+ */
+ public final int type;
+
+ /**
+ * Information identifying a Wi-Fi network. Only set when {@link #type} equals
+ * {@link #TYPE_WIFI}.
+ */
+ public final WifiKey wifiKey;
+
+ /**
+ * Construct a new {@link NetworkKey} for a Wi-Fi network.
+ * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network.
+ */
+ public NetworkKey(WifiKey wifiKey) {
+ this.type = TYPE_WIFI;
+ this.wifiKey = wifiKey;
+ }
+
+ private NetworkKey(Parcel in) {
+ type = in.readInt();
+ switch (type) {
+ case TYPE_WIFI:
+ wifiKey = WifiKey.CREATOR.createFromParcel(in);
+ break;
+ default:
+ throw new IllegalArgumentException("Parcel has unknown type: " + type);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(type);
+ switch (type) {
+ case TYPE_WIFI:
+ wifiKey.writeToParcel(out, flags);
+ break;
+ default:
+ throw new IllegalStateException("NetworkKey has unknown type " + type);
+ }
+ }
+
+ @Override
+ public String toString() {
+ switch (type) {
+ case TYPE_WIFI:
+ return wifiKey.toString();
+ default:
+ // Don't throw an exception here in case someone is logging this object in a catch
+ // block for debugging purposes.
+ return "InvalidKey";
+ }
+ }
+
+ public static final Parcelable.Creator<NetworkKey> CREATOR =
+ new Parcelable.Creator<NetworkKey>() {
+ @Override
+ public NetworkKey createFromParcel(Parcel in) {
+ return new NetworkKey(in);
+ }
+
+ @Override
+ public NetworkKey[] newArray(int size) {
+ return new NetworkKey[size];
+ }
+ };
+}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
new file mode 100644
index 0000000..3430547
--- /dev/null
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+
+/**
+ * Class that manages communication between network subsystems and a network scorer.
+ *
+ * <p>You can get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String)}:
+ *
+ * <pre>NetworkScoreManager manager =
+ * (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE)</pre>
+ *
+ * <p>A network scorer is any application which:
+ * <ul>
+ * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+ * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
+ * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission which scores networks
+ * and (eventually) calls {@link #updateScores} with the results.
+ * </ul>
+ *
+ * <p>The system keeps track of a default scorer application; at any time, only this application
+ * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
+ * {@link #updateScores}. Applications may determine the current default scorer with
+ * {@link #getDefaultScorerPackage()} and request to change the default scorer by sending an
+ * {@link #ACTION_CHANGE_DEFAULT} broadcast with another scorer.
+ *
+ * @hide
+ */
+public class NetworkScoreManager {
+ /**
+ * Activity action: ask the user to change the default network scorer. This will show a dialog
+ * that asks the user whether they want to replace the current default scorer with the one
+ * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
+ * default was changed or RESULT_CANCELED if it failed for any reason.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_CHANGE_DEFAULT = "android.net.scoring.CHANGE_DEFAULT";
+
+ /**
+ * Extra used with {@link #ACTION_CHANGE_DEFAULT} to specify the new scorer package. Set with
+ * {@link android.content.Intent#putExtra(String, String)}.
+ */
+ public static final String EXTRA_PACKAGE_NAME = "packageName";
+
+ /**
+ * Broadcast action: new network scores are being requested. This intent will only be delivered
+ * to the current default scorer app. That app is responsible for scoring the networks and
+ * calling {@link #updateScores} when complete. The networks to score are specified in
+ * {@link #EXTRA_NETWORKS_TO_SCORE}, and will generally consist of all networks which have been
+ * configured by the user as well as any open networks.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
+
+ /**
+ * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
+ * array of {@link NetworkKey}s. Can be obtained with
+ * {@link android.content.Intent#getParcelableArrayExtra(String)}}.
+ */
+ public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
+
+ private final Context mContext;
+
+ /** @hide */
+ public NetworkScoreManager(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Obtain the package name of the current default network scorer.
+ *
+ * At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
+ * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
+ * determine the current scorer and offer the user the ability to select a different scorer via
+ * the {@link #ACTION_CHANGE_DEFAULT} intent.
+ * @return the full package name of the current default scorer, or null if there is no active
+ * scorer.
+ */
+ public String getDefaultScorerPackage() {
+ // TODO: Implement.
+ return null;
+ }
+
+ /**
+ * Update network scores.
+ *
+ * This may be called at any time to re-score active networks. Scores will generally be updated
+ * quickly, but if this method is called too frequently, the scores may be held and applied at
+ * a later time.
+ *
+ * @param networks the networks which have been scored by the scorer.
+ * @throws SecurityException if the caller is not the default scorer.
+ */
+ public void updateScores(ScoredNetwork[] networks) throws SecurityException {
+ // TODO: Implement.
+ }
+}
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
new file mode 100644
index 0000000..7af7998
--- /dev/null
+++ b/core/java/android/net/RssiCurve.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A curve defining the network score over a range of RSSI values.
+ *
+ * <p>For each RSSI bucket, the score may be any byte. Scores have no absolute meaning and are only
+ * considered relative to other scores assigned by the same scorer. Networks with no score are all
+ * considered equivalent and ranked below any network with a score.
+ *
+ * <p>For example, consider a curve starting at -110 dBm with a bucket width of 10 and the
+ * following buckets: {@code [-20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]}.
+ * This represents a linear curve between -110 dBm and 30 dBm. It scores progressively higher at
+ * stronger signal strengths.
+ *
+ * <p>A network can be assigned a fixed score independent of RSSI by setting
+ * {@link #rssiBuckets} to a one-byte array whose element is the fixed score. {@link #start}
+ * should be set to the lowest RSSI value at which this fixed score should apply, and
+ * {@link #bucketWidth} should be set such that {@code start + bucketWidth} is equal to the
+ * highest RSSI value at which this fixed score should apply.
+ *
+ * <p>Note that RSSI values below -110 dBm or above 30 dBm are unlikely to cause any difference
+ * in connectivity behavior from those endpoints. That is, the connectivity framework will treat
+ * a network with a -120 dBm signal exactly as it would treat one with a -110 dBm signal.
+ * Therefore, graphs which specify scores outside this range may be truncated to this range by
+ * the system.
+ *
+ * @see ScoredNetwork
+ * @hide
+ */
+public class RssiCurve implements Parcelable {
+
+ /** The starting dBm of the curve. */
+ public final int start;
+
+ /** The width of each RSSI bucket, in dBm. */
+ public final int bucketWidth;
+
+ /** The score for each RSSI bucket. */
+ public final byte[] rssiBuckets;
+
+ /**
+ * Construct a new {@link RssiCurve}.
+ *
+ * @param start the starting dBm of the curve.
+ * @param bucketWidth the width of each RSSI bucket, in dBm.
+ * @param rssiBuckets the score for each RSSI bucket.
+ */
+ public RssiCurve(int start, int bucketWidth, byte[] rssiBuckets) {
+ this.start = start;
+ this.bucketWidth = bucketWidth;
+ if (rssiBuckets == null || rssiBuckets.length == 0) {
+ throw new IllegalArgumentException("rssiBuckets must be at least one element large.");
+ }
+ this.rssiBuckets = rssiBuckets;
+ }
+
+ private RssiCurve(Parcel in) {
+ start = in.readInt();
+ bucketWidth = in.readInt();
+ int bucketCount = in.readInt();
+ rssiBuckets = new byte[bucketCount];
+ in.readByteArray(rssiBuckets);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(start);
+ out.writeInt(bucketWidth);
+ out.writeInt(rssiBuckets.length);
+ out.writeByteArray(rssiBuckets);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("RssiCurve[start=")
+ .append(start)
+ .append(",bucketWidth=")
+ .append(bucketWidth);
+
+ sb.append(",buckets=");
+ for (int i = 0; i < rssiBuckets.length; i++) {
+ sb.append(rssiBuckets[i]);
+ if (i < rssiBuckets.length - 1) {
+ sb.append(",");
+ }
+ }
+ sb.append("]");
+
+ return sb.toString();
+ }
+
+ public static final Creator<RssiCurve> CREATOR =
+ new Creator<RssiCurve>() {
+ @Override
+ public RssiCurve createFromParcel(Parcel in) {
+ return new RssiCurve(in);
+ }
+
+ @Override
+ public RssiCurve[] newArray(int size) {
+ return new RssiCurve[size];
+ }
+ };
+}
diff --git a/core/java/android/net/ScoredNetwork.aidl b/core/java/android/net/ScoredNetwork.aidl
new file mode 100644
index 0000000..f83db11
--- /dev/null
+++ b/core/java/android/net/ScoredNetwork.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.net;
+
+parcelable ScoredNetwork;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
new file mode 100644
index 0000000..8af3c3c
--- /dev/null
+++ b/core/java/android/net/ScoredNetwork.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A network identifier along with a score for the quality of that network.
+ *
+ * @hide
+ */
+public class ScoredNetwork implements Parcelable {
+
+ /** A {@link NetworkKey} uniquely identifying this network. */
+ public final NetworkKey networkKey;
+
+ /**
+ * The {@link RssiCurve} representing the scores for this network based on the RSSI.
+ *
+ * <p>This field is optional and may be set to null to indicate that no score is available for
+ * this network at this time. Such networks, along with networks for which the scorer has not
+ * responded, are always prioritized below scored networks, regardless of the score.
+ */
+ public final RssiCurve rssiCurve;
+
+ /**
+ * Construct a new {@link ScoredNetwork}.
+ *
+ * @param networkKey the {@link NetworkKey} uniquely identifying this network.
+ * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+ * RSSI. This field is optional, and may be skipped to represent a network which the scorer
+ * has opted not to score at this time. Passing a null value here is strongly preferred to
+ * not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+ * indicates to the system not to request scores for this network in the future, although
+ * the scorer may choose to issue an out-of-band update at any time.
+ */
+ public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
+ this.networkKey = networkKey;
+ this.rssiCurve = rssiCurve;
+ }
+
+ private ScoredNetwork(Parcel in) {
+ networkKey = NetworkKey.CREATOR.createFromParcel(in);
+ if (in.readByte() == 1) {
+ rssiCurve = RssiCurve.CREATOR.createFromParcel(in);
+ } else {
+ rssiCurve = null;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ networkKey.writeToParcel(out, flags);
+ if (rssiCurve != null) {
+ out.writeByte((byte) 1);
+ rssiCurve.writeToParcel(out, flags);
+ } else {
+ out.writeByte((byte) 0);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
+ }
+
+ public static final Parcelable.Creator<ScoredNetwork> CREATOR =
+ new Parcelable.Creator<ScoredNetwork>() {
+ @Override
+ public ScoredNetwork createFromParcel(Parcel in) {
+ return new ScoredNetwork(in);
+ }
+
+ @Override
+ public ScoredNetwork[] newArray(int size) {
+ return new ScoredNetwork[size];
+ }
+ };
+}
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
new file mode 100644
index 0000000..ffcd85a
--- /dev/null
+++ b/core/java/android/net/WifiKey.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.regex.Pattern;
+
+/**
+ * Information identifying a Wi-Fi network.
+ * @see NetworkKey
+ *
+ * @hide
+ */
+public class WifiKey implements Parcelable {
+
+ // Patterns used for validation.
+ private static final Pattern SSID_PATTERN = Pattern.compile("(\".*\")|(0x[\\p{XDigit}]+)");
+ private static final Pattern BSSID_PATTERN =
+ Pattern.compile("([\\p{XDigit}]{2}:){5}[\\p{XDigit}]{2}");
+
+ /**
+ * The service set identifier (SSID) of an 802.11 network. If the SSID can be decoded as
+ * UTF-8, it will be surrounded by double quotation marks. Otherwise, it will be a string of
+ * hex digits starting with 0x.
+ */
+ public final String ssid;
+
+ /**
+ * The basic service set identifier (BSSID) of an access point for this network. This will
+ * be in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}, where each X is a
+ * hexadecimal digit.
+ */
+ public final String bssid;
+
+ /**
+ * Construct a new {@link WifiKey} for the given Wi-Fi SSID/BSSID pair.
+ *
+ * @param ssid the service set identifier (SSID) of an 802.11 network. If the SSID can be
+ * decoded as UTF-8, it should be surrounded by double quotation marks. Otherwise,
+ * it should be a string of hex digits starting with 0x.
+ * @param bssid the basic service set identifier (BSSID) of this network's access point.
+ * This should be in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX},
+ * where each X is a hexadecimal digit.
+ * @throws IllegalArgumentException if either the SSID or BSSID is invalid.
+ */
+ public WifiKey(String ssid, String bssid) {
+ if (!SSID_PATTERN.matcher(ssid).matches()) {
+ throw new IllegalArgumentException("Invalid ssid: " + ssid);
+ }
+ if (!BSSID_PATTERN.matcher(bssid).matches()) {
+ throw new IllegalArgumentException("Invalid bssid: " + bssid);
+ }
+ this.ssid = ssid;
+ this.bssid = bssid;
+ }
+
+ private WifiKey(Parcel in) {
+ ssid = in.readString();
+ bssid = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(ssid);
+ out.writeString(bssid);
+ }
+
+ @Override
+ public String toString() {
+ return "WifiKey[SSID=" + ssid + ",BSSID=" + bssid + "]";
+ }
+
+ public static final Creator<WifiKey> CREATOR =
+ new Creator<WifiKey>() {
+ @Override
+ public WifiKey createFromParcel(Parcel in) {
+ return new WifiKey(in);
+ }
+
+ @Override
+ public WifiKey[] newArray(int size) {
+ return new WifiKey[size];
+ }
+ };
+}
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 205a21d..6fdb0d0 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -18,8 +18,15 @@
import android.os.Parcelable;
import android.os.Parcel;
+import android.util.Log;
+import android.util.ArrayMap;
+import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+
/**
* A class representing service information for network service discovery
@@ -27,11 +34,13 @@
*/
public final class NsdServiceInfo implements Parcelable {
+ private static final String TAG = "NsdServiceInfo";
+
private String mServiceName;
private String mServiceType;
- private DnsSdTxtRecord mTxtRecord;
+ private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<String, byte[]>();
private InetAddress mHost;
@@ -41,10 +50,9 @@
}
/** @hide */
- public NsdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
+ public NsdServiceInfo(String sn, String rt) {
mServiceName = sn;
mServiceType = rt;
- mTxtRecord = tr;
}
/** Get the service name */
@@ -67,16 +75,6 @@
mServiceType = s;
}
- /** @hide */
- public DnsSdTxtRecord getTxtRecord() {
- return mTxtRecord;
- }
-
- /** @hide */
- public void setTxtRecord(DnsSdTxtRecord t) {
- mTxtRecord = new DnsSdTxtRecord(t);
- }
-
/** Get the host address. The host address is valid for a resolved service. */
public InetAddress getHost() {
return mHost;
@@ -97,14 +95,134 @@
mPort = p;
}
+ /** @hide */
+ public void setAttribute(String key, byte[] value) {
+ // Key must be printable US-ASCII, excluding =.
+ for (int i = 0; i < key.length(); ++i) {
+ char character = key.charAt(i);
+ if (character < 0x20 || character > 0x7E) {
+ throw new IllegalArgumentException("Key strings must be printable US-ASCII");
+ } else if (character == 0x3D) {
+ throw new IllegalArgumentException("Key strings must not include '='");
+ }
+ }
+
+ // Key length + value length must be < 255.
+ if (key.length() + (value == null ? 0 : value.length) >= 255) {
+ throw new IllegalArgumentException("Key length + value length must be < 255 bytes");
+ }
+
+ // Warn if key is > 9 characters, as recommended by RFC 6763 section 6.4.
+ if (key.length() > 9) {
+ Log.w(TAG, "Key lengths > 9 are discouraged: " + key);
+ }
+
+ // Check against total TXT record size limits.
+ // Arbitrary 400 / 1300 byte limits taken from RFC 6763 section 6.2.
+ int txtRecordSize = getTxtRecordSize();
+ int futureSize = txtRecordSize + key.length() + (value == null ? 0 : value.length) + 2;
+ if (futureSize > 1300) {
+ throw new IllegalArgumentException("Total length of attributes must be < 1300 bytes");
+ } else if (futureSize > 400) {
+ Log.w(TAG, "Total length of all attributes exceeds 400 bytes; truncation may occur");
+ }
+
+ mTxtRecord.put(key, value);
+ }
+
+ /**
+ * Add a service attribute as a key/value pair.
+ *
+ * <p> Service attributes are included as DNS-SD TXT record pairs.
+ *
+ * <p> The key must be US-ASCII printable characters, excluding the '=' character. Values may
+ * be UTF-8 strings or null. The total length of key + value must be less than 255 bytes.
+ *
+ * <p> Keys should be short, ideally no more than 9 characters, and unique per instance of
+ * {@link NsdServiceInfo}. Calling {@link #setAttribute} twice with the same key will overwrite
+ * first value.
+ */
+ public void setAttribute(String key, String value) {
+ try {
+ setAttribute(key, value == null ? (byte []) null : value.getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException("Value must be UTF-8");
+ }
+ }
+
+ /** Remove an attribute by key */
+ public void removeAttribute(String key) {
+ mTxtRecord.remove(key);
+ }
+
+ /**
+ * Retrive attributes as a map of String keys to byte[] values.
+ *
+ * <p> The returned map is unmodifiable; changes must be made through {@link #setAttribute} and
+ * {@link #removeAttribute}.
+ */
+ public Map<String, byte[]> getAttributes() {
+ return Collections.unmodifiableMap(mTxtRecord);
+ }
+
+ private int getTxtRecordSize() {
+ int txtRecordSize = 0;
+ for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
+ txtRecordSize += 2; // One for the length byte, one for the = between key and value.
+ txtRecordSize += entry.getKey().length();
+ byte[] value = entry.getValue();
+ txtRecordSize += value == null ? 0 : value.length;
+ }
+ return txtRecordSize;
+ }
+
+ /** @hide */
+ public byte[] getTxtRecord() {
+ int txtRecordSize = getTxtRecordSize();
+ if (txtRecordSize == 0) {
+ return null;
+ }
+
+ byte[] txtRecord = new byte[txtRecordSize];
+ int ptr = 0;
+ for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
+ String key = entry.getKey();
+ byte[] value = entry.getValue();
+
+ // One byte to record the length of this key/value pair.
+ txtRecord[ptr++] = (byte) (key.length() + (value == null ? 0 : value.length) + 1);
+
+ // The key, in US-ASCII.
+ // Note: use the StandardCharsets const here because it doesn't raise exceptions and we
+ // already know the key is ASCII at this point.
+ System.arraycopy(key.getBytes(StandardCharsets.US_ASCII), 0, txtRecord, ptr,
+ key.length());
+ ptr += key.length();
+
+ // US-ASCII '=' character.
+ txtRecord[ptr++] = (byte)'=';
+
+ // The value, as any raw bytes.
+ if (value != null) {
+ System.arraycopy(value, 0, txtRecord, ptr, value.length);
+ ptr += value.length;
+ }
+ }
+ return txtRecord;
+ }
+
public String toString() {
StringBuffer sb = new StringBuffer();
- sb.append("name: ").append(mServiceName).
- append("type: ").append(mServiceType).
- append("host: ").append(mHost).
- append("port: ").append(mPort).
- append("txtRecord: ").append(mTxtRecord);
+ sb.append("name: ").append(mServiceName)
+ .append(", type: ").append(mServiceType)
+ .append(", host: ").append(mHost)
+ .append(", port: ").append(mPort);
+
+ byte[] txtRecord = getTxtRecord();
+ if (txtRecord != null) {
+ sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
+ }
return sb.toString();
}
@@ -117,14 +235,27 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mServiceName);
dest.writeString(mServiceType);
- dest.writeParcelable(mTxtRecord, flags);
if (mHost != null) {
- dest.writeByte((byte)1);
+ dest.writeInt(1);
dest.writeByteArray(mHost.getAddress());
} else {
- dest.writeByte((byte)0);
+ dest.writeInt(0);
}
dest.writeInt(mPort);
+
+ // TXT record key/value pairs.
+ dest.writeInt(mTxtRecord.size());
+ for (String key : mTxtRecord.keySet()) {
+ byte[] value = mTxtRecord.get(key);
+ if (value != null) {
+ dest.writeInt(1);
+ dest.writeInt(value.length);
+ dest.writeByteArray(value);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeString(key);
+ }
}
/** Implement the Parcelable interface */
@@ -134,15 +265,26 @@
NsdServiceInfo info = new NsdServiceInfo();
info.mServiceName = in.readString();
info.mServiceType = in.readString();
- info.mTxtRecord = in.readParcelable(null);
- if (in.readByte() == 1) {
+ if (in.readInt() == 1) {
try {
info.mHost = InetAddress.getByAddress(in.createByteArray());
} catch (java.net.UnknownHostException e) {}
}
info.mPort = in.readInt();
+
+ // TXT record key/value pairs.
+ int recordCount = in.readInt();
+ for (int i = 0; i < recordCount; ++i) {
+ byte[] valueArray = null;
+ if (in.readInt() == 1) {
+ int valueLength = in.readInt();
+ valueArray = new byte[valueLength];
+ in.readByteArray(valueArray);
+ }
+ info.mTxtRecord.put(in.readString(), valueArray);
+ }
return info;
}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 2e38960..f339e52 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,9 +16,15 @@
package android.os;
+import android.os.BatteryProperty;
+import android.os.IBatteryPropertiesRegistrar;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
/**
* The BatteryManager class contains strings and constants used for values
- * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent.
+ * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent, and
+ * provides a method for querying battery and charging properties.
*/
public class BatteryManager {
/**
@@ -121,4 +127,30 @@
/** @hide */
public static final int BATTERY_PLUGGED_ANY =
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+
+ private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
+
+ /**
+ * Return the requested battery property.
+ *
+ * @param id identifier from {@link BatteryProperty} of the requested property
+ * @return a {@link BatteryProperty} object that returns the property value, or null on error
+ */
+ public BatteryProperty getProperty(int id) throws RemoteException {
+ if (mBatteryPropertiesRegistrar == null) {
+ IBinder b = ServiceManager.getService("batteryproperties");
+ mBatteryPropertiesRegistrar =
+ IBatteryPropertiesRegistrar.Stub.asInterface(b);
+
+ if (mBatteryPropertiesRegistrar == null)
+ return null;
+ }
+
+ BatteryProperty prop = new BatteryProperty(Integer.MIN_VALUE);
+ if ((mBatteryPropertiesRegistrar.getProperty(id, prop) == 0) &&
+ (prop.getInt() != Integer.MIN_VALUE))
+ return prop;
+ else
+ return null;
+ }
}
diff --git a/core/java/android/os/BatteryProperty.java b/core/java/android/os/BatteryProperty.java
index 76b0dc4..ec73952 100644
--- a/core/java/android/os/BatteryProperty.java
+++ b/core/java/android/os/BatteryProperty.java
@@ -19,22 +19,67 @@
import android.os.Parcelable;
/**
- * {@hide}
+ * Battery properties that may be queried using
+ * {@link BatteryManager#getProperty
+ * BatteryManager.getProperty()}
*/
public class BatteryProperty implements Parcelable {
/*
* Battery property identifiers. These must match the values in
* frameworks/native/include/batteryservice/BatteryService.h
*/
- public static final int BATTERY_PROP_CHARGE_COUNTER = 1;
- public static final int BATTERY_PROP_CURRENT_NOW = 2;
- public static final int BATTERY_PROP_CURRENT_AVG = 3;
- public static final int BATTERY_PROP_CAPACITY = 4;
+ /** Battery capacity in microampere-hours, as an integer. */
+ public static final int CHARGE_COUNTER = 1;
- public int valueInt;
+ /**
+ * Instantaneous battery current in microamperes, as an integer. Positive
+ * values indicate net current entering the battery from a charge source,
+ * negative values indicate net current discharging from the battery.
+ */
+ public static final int CURRENT_NOW = 2;
+ /**
+ * Average battery current in microamperes, as an integer. Positive
+ * values indicate net current entering the battery from a charge source,
+ * negative values indicate net current discharging from the battery.
+ * The time period over which the average is computed may depend on the
+ * fuel gauge hardware and its configuration.
+ */
+ public static final int CURRENT_AVERAGE = 3;
+
+ /**
+ * Remaining battery capacity as an integer percentage of total capacity
+ * (with no fractional part).
+ */
+ public static final int CAPACITY = 4;
+
+ private int mValueInt;
+
+ /**
+ * @hide
+ */
+ public BatteryProperty(int value) {
+ mValueInt = value;
+ }
+
+ /**
+ * @hide
+ */
public BatteryProperty() {
- valueInt = Integer.MIN_VALUE;
+ mValueInt = Integer.MIN_VALUE;
+ }
+
+ /**
+ * Return the value of a property of integer type previously queried
+ * via {@link BatteryManager#getProperty
+ * BatteryManager.getProperty()}. If the platform does
+ * not provide the property queried, this value will be
+ * Integer.MIN_VALUE.
+ *
+ * @return The queried property value, or Integer.MIN_VALUE if not supported.
+ */
+ public int getInt() {
+ return mValueInt;
}
/*
@@ -47,11 +92,11 @@
}
public void readFromParcel(Parcel p) {
- valueInt = p.readInt();
+ mValueInt = p.readInt();
}
public void writeToParcel(Parcel p, int flags) {
- p.writeInt(valueInt);
+ p.writeInt(mValueInt);
}
public static final Parcelable.Creator<BatteryProperty> CREATOR
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 4854bc0..4d05e2d 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -20,8 +20,8 @@
interface IVibratorService
{
boolean hasVibrator();
- void vibrate(int uid, String packageName, long milliseconds, int streamHint, IBinder token);
- void vibratePattern(int uid, String packageName, in long[] pattern, int repeat, int streamHint, IBinder token);
+ void vibrate(int uid, String opPkg, long milliseconds, int streamHint, IBinder token);
+ void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int streamHint, IBinder token);
void cancelVibrate(IBinder token);
}
diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java
index 536da32..7b870ac 100644
--- a/core/java/android/os/NullVibrator.java
+++ b/core/java/android/os/NullVibrator.java
@@ -40,7 +40,7 @@
* @hide
*/
@Override
- public void vibrate(int owningUid, String owningPackage, long milliseconds, int streamHint) {
+ public void vibrate(int uid, String opPkg, long milliseconds, int streamHint) {
vibrate(milliseconds);
}
@@ -48,7 +48,7 @@
* @hide
*/
@Override
- public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+ public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
int streamHint) {
if (repeat >= pattern.length) {
throw new ArrayIndexOutOfBoundsException();
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 13bc4f6..8d9cf54 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -58,13 +58,13 @@
* @hide
*/
@Override
- public void vibrate(int owningUid, String owningPackage, long milliseconds, int streamHint) {
+ public void vibrate(int uid, String opPkg, long milliseconds, int streamHint) {
if (mService == null) {
Log.w(TAG, "Failed to vibrate; no vibrator service.");
return;
}
try {
- mService.vibrate(owningUid, owningPackage, milliseconds, streamHint, mToken);
+ mService.vibrate(uid, opPkg, milliseconds, streamHint, mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
@@ -74,7 +74,7 @@
* @hide
*/
@Override
- public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+ public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
int streamHint) {
if (mService == null) {
Log.w(TAG, "Failed to vibrate; no vibrator service.");
@@ -85,7 +85,7 @@
// anyway
if (repeat < pattern.length) {
try {
- mService.vibratePattern(owningUid, owningPackage, pattern, repeat, streamHint,
+ mService.vibratePattern(uid, opPkg, pattern, repeat, streamHint,
mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 8845ba3..c1d4d4c 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -135,7 +135,7 @@
* Like {@link #vibrate(long, int)}, but allowing the caller to specify that
* the vibration is owned by someone else.
*/
- public abstract void vibrate(int owningUid, String owningPackage,
+ public abstract void vibrate(int uid, String opPkg,
long milliseconds, int streamHint);
/**
@@ -143,7 +143,7 @@
* Like {@link #vibrate(long[], int, int)}, but allowing the caller to specify that
* the vibration is owned by someone else.
*/
- public abstract void vibrate(int owningUid, String owningPackage,
+ public abstract void vibrate(int uid, String opPkg,
long[] pattern, int repeat, int streamHint);
/**
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 307ac39..a8b4cfb0 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -35,7 +35,7 @@
private static final String SETTINGS = "settings";
/**
- * Indexable references name.
+ * Indexable reference names.
*/
public static final String INDEXABLES_XML_RES = "indexables_xml_res";
@@ -45,7 +45,7 @@
public static final String INDEXABLES_XML_RES_PATH = SETTINGS + "/" + INDEXABLES_XML_RES;
/**
- * Indexable raw data name.
+ * Indexable raw data names.
*/
public static final String INDEXABLES_RAW = "indexables_raw";
@@ -55,6 +55,16 @@
public static final String INDEXABLES_RAW_PATH = SETTINGS + "/" + INDEXABLES_RAW;
/**
+ * Non indexable data keys.
+ */
+ public static final String NON_INDEXABLES_KEYS = "non_indexables_key";
+
+ /**
+ * ContentProvider path for non indexable data keys.
+ */
+ public static final String NON_INDEXABLES_KEYS_PATH = SETTINGS + "/" + NON_INDEXABLES_KEYS;
+
+ /**
* Indexable xml resources colums.
*/
public static final String[] INDEXABLES_XML_RES_COLUMNS = new String[] {
@@ -114,6 +124,17 @@
public static final int COLUMN_INDEX_RAW_INTENT_TARGET_CLASS = 11;
public static final int COLUMN_INDEX_RAW_KEY = 12;
+ /**
+ * Indexable raw data colums.
+ */
+ public static final String[] NON_INDEXABLES_KEYS_COLUMNS = new String[] {
+ NonIndexableKey.COLUMN_KEY_VALUE // 0
+ };
+
+ /**
+ * Non indexable data keys colums indices.
+ */
+ public static final int COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE = 0;
/**
* Constants related to a {@link SearchIndexableResource}.
@@ -186,6 +207,24 @@
}
/**
+ * Constants related to a {@link SearchIndexableResource} and {@link SearchIndexableData}.
+ *
+ * This is a description of a data (thru its unique key) that cannot be indexed.
+ */
+ public static final class NonIndexableKey extends BaseColumns {
+ private NonIndexableKey() {
+ }
+
+ public static final String MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +
+ "/" + NON_INDEXABLES_KEYS;
+
+ /**
+ * Key for the non indexable data.
+ */
+ public static final String COLUMN_KEY_VALUE = "key";
+ }
+
+ /**
* The base columns.
*/
private static class BaseColumns {
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index 2e358e4..9c8f6d0 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -69,6 +69,7 @@
private static final int MATCH_RES_CODE = 1;
private static final int MATCH_RAW_CODE = 2;
+ private static final int MATCH_NON_INDEXABLE_KEYS_CODE = 3;
/**
* Implementation is provided by the parent class.
@@ -82,6 +83,8 @@
MATCH_RES_CODE);
mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_RAW_PATH,
MATCH_RAW_CODE);
+ mMatcher.addURI(mAuthority, SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH,
+ MATCH_NON_INDEXABLE_KEYS_CODE);
// Sanity check our setup
if (!info.exported) {
@@ -105,6 +108,8 @@
return queryXmlResources(null);
case MATCH_RAW_CODE:
return queryRawData(null);
+ case MATCH_NON_INDEXABLE_KEYS_CODE:
+ return queryNonIndexableKeys(null);
default:
throw new UnsupportedOperationException("Unknown Uri " + uri);
}
@@ -113,7 +118,7 @@
/**
* Returns all {@link android.provider.SearchIndexablesContract.XmlResource}.
*
- * Those are usually xml resource ID to some {@link android.preference.PreferenceScreen}.
+ * Those are Xml resource IDs to some {@link android.preference.PreferenceScreen}.
*
* @param projection list of {@link android.provider.SearchIndexablesContract.XmlResource}
* columns to put into the cursor. If {@code null} all supported columns
@@ -124,7 +129,7 @@
/**
* Returns all {@link android.provider.SearchIndexablesContract.RawData}.
*
- * Those are raw indexable data.
+ * Those are the raw indexable data.
*
* @param projection list of {@link android.provider.SearchIndexablesContract.RawData} columns
* to put into the cursor. If {@code null} all supported columns should be
@@ -132,6 +137,17 @@
*/
public abstract Cursor queryRawData(String[] projection);
+ /**
+ * Returns all {@link android.provider.SearchIndexablesContract.NonIndexableKey}.
+ *
+ * Those are the non indexable data keys.
+ *
+ * @param projection list of {@link android.provider.SearchIndexablesContract.NonIndexableKey}
+ * columns to put into the cursor. If {@code null} all supported columns
+ * should be included.
+ */
+ public abstract Cursor queryNonIndexableKeys(String[] projection);
+
@Override
public String getType(Uri uri) {
switch (mMatcher.match(uri)) {
@@ -139,14 +155,15 @@
return SearchIndexablesContract.XmlResource.MIME_TYPE;
case MATCH_RAW_CODE:
return SearchIndexablesContract.RawData.MIME_TYPE;
+ case MATCH_NON_INDEXABLE_KEYS_CODE:
+ return SearchIndexablesContract.NonIndexableKey.MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
/**
- * Implementation is provided by the parent class. Throws by default, and
- * cannot be overriden.
+ * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
*/
@Override
public final Uri insert(Uri uri, ContentValues values) {
@@ -154,8 +171,7 @@
}
/**
- * Implementation is provided by the parent class. Throws by default, and
- * cannot be overriden.
+ * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
*/
@Override
public final int delete(Uri uri, String selection, String[] selectionArgs) {
@@ -163,8 +179,7 @@
}
/**
- * Implementation is provided by the parent class. Throws by default, and
- * cannot be overriden.
+ * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
*/
@Override
public final int update(
diff --git a/core/java/android/provider/TvContract.java b/core/java/android/provider/TvContract.java
new file mode 100644
index 0000000..233e0ca
--- /dev/null
+++ b/core/java/android/provider/TvContract.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2014 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.provider;
+
+import android.content.ContentUris;
+import android.net.Uri;
+
+/**
+ * <p>
+ * The contract between the TV provider and applications. Contains definitions for the supported
+ * URIs and columns.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * TvContract defines a basic database of TV content metadata such as channel and program
+ * information. The information is stored in {@link Channels} and {@link Programs} tables.
+ * </p>
+ * <ul>
+ * <li>A row in the {@link Channels} table represents information about a TV channel. The data
+ * format can vary greatly from standard to standard or according to service provider, thus
+ * the columns here are mostly comprised of basic entities that are usually seen to users
+ * regardless of standard such as channel number and name.</li>
+ * <li>A row in the {@link Programs} table represents a set of data describing a TV program such
+ * as program title and start time.</li>
+ * </ul>
+ */
+public final class TvContract {
+ /** The authority for the TV provider. */
+ public static final String AUTHORITY = "com.android.tv";
+
+ /**
+ * Builds a URI that points to a specific channel.
+ *
+ * @param channelId The ID of the channel to point to.
+ */
+ public static final Uri buildChannelUri(long channelId) {
+ return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
+ }
+
+ /**
+ * Builds a URI that points to a specific program.
+ *
+ * @param programId The ID of the program to point to.
+ */
+ public static final Uri buildProgramUri(long programId) {
+ return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
+ }
+
+ /**
+ * Builds a URI that points to a specific program the user watched.
+ *
+ * @param watchedProgramId The ID of the watched program to point to.
+ * @hide
+ */
+ public static final Uri buildWatchedProgramUri(long watchedProgramId) {
+ return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
+ }
+
+ private TvContract() {}
+
+ /**
+ * Common base for the tables of TV channels/programs.
+ */
+ public interface BaseTvColumns extends BaseColumns {
+ /**
+ * The name of the package that owns a row in each table.
+ * <p>
+ * The TV provider fills it in with the name of the package that provides the initial data
+ * of that row. If the package is later uninstalled, the rows it owns are automatically
+ * removed from the tables.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String PACKAGE_NAME = "package_name";
+ }
+
+ /** Column definitions for the TV channels table. */
+ public static final class Channels implements BaseTvColumns {
+
+ /** The content:// style URI for this table. */
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/channel");
+
+ /** The MIME type of a directory of TV channels. */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+
+ /** The MIME type of a single TV channel. */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/vnd.com.android.tv.channels";
+
+ /** A generic channel type. */
+ public static final int TYPE_OTHER = 0x0;
+
+ /** The special channel type used for pass-through inputs such as HDMI. */
+ public static final int TYPE_PASSTHROUGH = 0x00010000;
+
+ /** The channel type for DVB-T (terrestrial). */
+ public static final int TYPE_DVB_T = 0x00020000;
+
+ /** The channel type for DVB-T2 (terrestrial). */
+ public static final int TYPE_DVB_T2 = 0x00020001;
+
+ /** The channel type for DVB-S (satellite). */
+ public static final int TYPE_DVB_S = 0x00020100;
+
+ /** The channel type for DVB-S2 (satellite). */
+ public static final int TYPE_DVB_S2 = 0x00020101;
+
+ /** The channel type for DVB-C (cable). */
+ public static final int TYPE_DVB_C = 0x00020200;
+
+ /** The channel type for DVB-C2 (cable). */
+ public static final int TYPE_DVB_C2 = 0x00020201;
+
+ /** The channel type for DVB-H (handheld). */
+ public static final int TYPE_DVB_H = 0x00020300;
+
+ /** The channel type for DVB-SH (satellite). */
+ public static final int TYPE_DVB_SH = 0x00020400;
+
+ /** The channel type for ATSC (terrestrial/cable). */
+ public static final int TYPE_ATSC = 0x00030000;
+
+ /** The channel type for ATSC 2.0. */
+ public static final int TYPE_ATSC_2_0 = 0x00030001;
+
+ /** The channel type for ATSC-M/H (mobile/handheld). */
+ public static final int TYPE_ATSC_M_H = 0x00030100;
+
+ /** The channel type for ISDB-T (terrestrial). */
+ public static final int TYPE_ISDB_T = 0x00040000;
+
+ /** The channel type for ISDB-Tb (Brazil). */
+ public static final int TYPE_ISDB_TB = 0x00040100;
+
+ /** The channel type for ISDB-S (satellite). */
+ public static final int TYPE_ISDB_S = 0x00040200;
+
+ /** The channel type for ISDB-C (cable). */
+ public static final int TYPE_ISDB_C = 0x00040300;
+
+ /** The channel type for 1seg (handheld). */
+ public static final int TYPE_1SEG = 0x00040400;
+
+ /** The channel type for DTMB (terrestrial). */
+ public static final int TYPE_DTMB = 0x00050000;
+
+ /** The channel type for CMMB (handheld). */
+ public static final int TYPE_CMMB = 0x00050100;
+
+ /** The channel type for T-DMB (terrestrial). */
+ public static final int TYPE_T_DMB = 0x00060000;
+
+ /** The channel type for S-DMB (satellite). */
+ public static final int TYPE_S_DMB = 0x00060100;
+
+ /**
+ * The name of the TV input service that provides this TV channel.
+ * <p>
+ * This is a required field.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String SERVICE_NAME = "service_name";
+
+ /**
+ * The predefined type of this TV channel.
+ * <p>
+ * This is used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the current
+ * channel conforms to.
+ * </p><p>
+ * This is a required field.
+ * </p><p>
+ * Type: INTEGER
+ * </p>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * The transport stream ID as appeared in various broadcast standards.
+ * <p>
+ * This is not a required field but if provided, can significantly increase the accuracy of
+ * channel identification.
+ * </p><p>
+ * Type: INTEGER
+ * </p>
+ */
+ public static final String TRANSPORT_STREAM_ID = "transport_stream_id";
+
+ /**
+ * The channel number that is displayed to the user.
+ * <p>
+ * The format can vary depending on broadcast standard and product specification.
+ * </p><p>
+ * Type: INTEGER
+ * </p>
+ */
+ public static final String DISPLAY_NUMBER = "display_number";
+
+ /**
+ * The channel name that is displayed to the user.
+ * <p>
+ * A call sign is a good candidate to use for this purpose but any name that helps the user
+ * recognize the current channel will be enough. Can also be empty depending on broadcast
+ * standard.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String DISPLAY_NAME = "display_name";
+
+ /**
+ * The description of this TV channel.
+ * <p>
+ * Can be empty initially.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String DESCRIPTION = "description";
+
+ /**
+ * The flag indicating whether this TV channel is browsable or not.
+ * <p>
+ * A value of 1 indicates the channel is included in the channel list that applications use
+ * to browse channels, a value of 0 indicates the channel is not included in the list. If
+ * not specified, this value is set to 1 by default.
+ * </p><p>
+ * Type: INTEGER (boolean)
+ * </p>
+ */
+ public static final String BROWSABLE = "browsable";
+
+ /**
+ * Generic data used by individual TV input services.
+ * <p>
+ * Type: BLOB
+ * </p>
+ */
+ public static final String DATA = "data";
+
+
+ /**
+ * The version number of this row entry used by TV input services.
+ * <p>
+ * This is best used by sync adapters to identify the rows to update. The number can be
+ * defined by individual TV input services. One may assign the same value as
+ * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
+ * coming from a TV broadcast.
+ * </p><p>
+ * Type: INTEGER
+ * </p>
+ */
+ public static final String VERSION_NUMBER = "version_number";
+
+ private Channels() {}
+ }
+
+ /** Column definitions for the TV programs table. */
+ public static final class Programs implements BaseTvColumns {
+
+ /** The content:// style URI for this table. */
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/program");
+
+ /** The MIME type of a directory of TV programs. */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+
+ /** The MIME type of a single TV program. */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/vnd.com.android.tv.programs";
+
+ /**
+ * The ID of the TV channel that contains this TV program.
+ * <p>
+ * This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+ * </p><p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String CHANNEL_ID = "channel_id";
+
+ /**
+ * The title of this TV program.
+ * <p>
+ * Type: TEXT
+ * </p>
+ **/
+ public static final String TITLE = "title";
+
+ /**
+ * The start time of this TV program, in milliseconds since the epoch.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+
+ /**
+ * The end time of this TV program, in milliseconds since the epoch.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+
+ /**
+ * The description of this TV program that is displayed to the user by default.
+ * <p>
+ * The maximum length of this field is 256 characters.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String DESCRIPTION = "description";
+
+ /**
+ * The detailed, lengthy description of this TV program that is displayed only when the user
+ * wants to see more information.
+ * <p>
+ * TV input services should leave this field empty if they have no additional
+ * details beyond {@link #DESCRIPTION}.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String LONG_DESCRIPTION = "long_description";
+
+ /**
+ * Generic data used by TV input services.
+ * <p>
+ * Type: BLOB
+ * </p>
+ */
+ public static final String DATA = "data";
+
+ /**
+ * The version number of this row entry used by TV input services.
+ * <p>
+ * This is best used by sync adapters to identify the rows to update. The number can be
+ * defined by individual TV input services. One may assign the same value as
+ * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
+ * broadcast.
+ * </p><p>
+ * Type: INTEGER
+ * </p>
+ */
+ public static final String VERSION_NUMBER = "version_number";
+
+ private Programs() {}
+ }
+
+ /**
+ * Column definitions for the TV programs that the user watched. Applications do not have access
+ * to this table.
+ *
+ * @hide
+ */
+ public static final class WatchedPrograms implements BaseColumns {
+
+ /** The content:// style URI for this table. */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://" + AUTHORITY + "/watched_program");
+
+ /** The MIME type of a directory of watched programs. */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/vnd.com.android.tv.watched_programs";
+
+ /** The MIME type of a single item in this table. */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/vnd.com.android.tv.watched_programs";
+
+ /**
+ * The UTC time that the user started watching this TV program, in milliseconds since the
+ * epoch.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String WATCH_START_TIME_UTC_MILLIS = "watch_start_time_utc_millis";
+
+ /**
+ * The UTC time that the user stopped watching this TV program, in milliseconds since the
+ * epoch.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
+
+ /**
+ * The channel ID that contains this TV program.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String CHANNEL_ID = "channel_id";
+
+ /**
+ * The title of this TV program.
+ * <p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String TITLE = "title";
+
+ /**
+ * The start time of this TV program, in milliseconds since the epoch.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+
+ /**
+ * The end time of this TV program, in milliseconds since the epoch.
+ * <p>
+ * Type: INTEGER (long)
+ * </p>
+ */
+ public static final String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+
+ /**
+ * The description of this TV program.
+ * <p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String DESCRIPTION = "description";
+
+ private WatchedPrograms() {}
+ }
+}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 0f74169..2c0b76d 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -32,7 +32,7 @@
private final String key;
private final int uid;
- private final String basePkg;
+ private final String opPkg;
private final int initialPid;
private final Notification notification;
private final UserHandle user;
@@ -41,26 +41,20 @@
private final int score;
/** @hide */
- public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
- Notification notification, UserHandle user) {
- this(pkg, null, id, tag, uid, initialPid, score, notification, user);
- }
-
- /** @hide */
- public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
+ public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
int initialPid, int score, Notification notification, UserHandle user) {
- this(pkg, basePkg, id, tag, uid, initialPid, score, notification, user,
+ this(pkg, opPkg, id, tag, uid, initialPid, score, notification, user,
System.currentTimeMillis());
}
- public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
+ public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
int initialPid, int score, Notification notification, UserHandle user,
long postTime) {
if (pkg == null) throw new NullPointerException();
if (notification == null) throw new NullPointerException();
this.pkg = pkg;
- this.basePkg = pkg;
+ this.opPkg = opPkg;
this.id = id;
this.tag = tag;
this.uid = uid;
@@ -75,7 +69,7 @@
public StatusBarNotification(Parcel in) {
this.pkg = in.readString();
- this.basePkg = in.readString();
+ this.opPkg = in.readString();
this.id = in.readInt();
if (in.readInt() != 0) {
this.tag = in.readString();
@@ -93,12 +87,12 @@
}
private String key() {
- return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
+ return pkg + '|' + opPkg + '|' + id + '|' + tag + '|' + uid;
}
public void writeToParcel(Parcel out, int flags) {
out.writeString(this.pkg);
- out.writeString(this.basePkg);
+ out.writeString(this.opPkg);
out.writeInt(this.id);
if (this.tag != null) {
out.writeInt(1);
@@ -139,14 +133,14 @@
public StatusBarNotification cloneLight() {
final Notification no = new Notification();
this.notification.cloneInto(no, false); // light copy
- return new StatusBarNotification(this.pkg, this.basePkg,
+ return new StatusBarNotification(this.pkg, this.opPkg,
this.id, this.tag, this.uid, this.initialPid,
this.score, no, this.user, this.postTime);
}
@Override
public StatusBarNotification clone() {
- return new StatusBarNotification(this.pkg, this.basePkg,
+ return new StatusBarNotification(this.pkg, this.opPkg,
this.id, this.tag, this.uid, this.initialPid,
this.score, this.notification.clone(), this.user, this.postTime);
}
@@ -205,9 +199,9 @@
return uid;
}
- /** The notifying app's base package. @hide */
- public String getBasePkg() {
- return basePkg;
+ /** The package used for AppOps tracking. @hide */
+ public String getOpPkg() {
+ return opPkg;
}
/** @hide */
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/core/java/android/tv/ITvInputSessionWrapper.java
index fd4e1e3..66fe5e1 100644
--- a/core/java/android/tv/ITvInputSessionWrapper.java
+++ b/core/java/android/tv/ITvInputSessionWrapper.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.net.Uri;
import android.os.Message;
+import android.tv.TvInputService.TvInputSessionImpl;
import android.util.Log;
import android.view.Surface;
@@ -38,10 +39,10 @@
private static final int DO_SET_VOLUME = 3;
private static final int DO_TUNE = 4;
- private TvInputSession mTvInputSession;
+ private TvInputSessionImpl mTvInputSession;
private final HandlerCaller mCaller;
- public ITvInputSessionWrapper(Context context, TvInputSession session) {
+ public ITvInputSessionWrapper(Context context, TvInputSessionImpl session) {
mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */);
mTvInputSession = session;
}
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index 0b6ab64..4cf2b35 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -282,7 +282,7 @@
}
/**
- * Creates a {@link TvInputSession} interface for a given TV input.
+ * Creates a {@link Session} for a given TV input.
* <p>
* The number of sessions that can be created at the same time is limited by the capability of
* the given TV input.
diff --git a/core/java/android/tv/TvInputService.java b/core/java/android/tv/TvInputService.java
index e43cc95..d7f6c32 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/core/java/android/tv/TvInputService.java
@@ -123,7 +123,7 @@
public abstract TvInputSessionImpl onCreateSession();
/**
- * Base class for derived classes to implement to provide {@link TvInputSession}.
+ * Base class for derived classes to implement to provide {@link TvInputManager.Session}.
*/
public abstract static class TvInputSessionImpl {
/**
@@ -155,52 +155,35 @@
* @return {@code true} the tuning was successful, {@code false} otherwise.
*/
public abstract boolean onTune(Uri channelUri);
- }
-
- /**
- * Internal implementation of {@link TvInputSession}. This takes care of basic maintenance of
- * the TV input session but most behavior must be implemented in {@link TvInputSessionImpl}
- * returned by {@link TvInputService#onCreateSession}.
- */
- private static class TvInputSessionImplInternal extends TvInputSession {
- private final TvInputSessionImpl mSessionImpl;
-
- public TvInputSessionImplInternal(TvInputSessionImpl sessionImpl) {
- mSessionImpl = sessionImpl;
- }
/**
* This method is called when the application would like to stop using the current input
* session.
*/
- @Override
- public final void release() {
- mSessionImpl.onRelease();
+ void release() {
+ onRelease();
}
/**
- * Calls {@link TvInputSessionImpl#onSetSurface}.
+ * Calls {@link onSetSurface}.
*/
- @Override
- public final void setSurface(Surface surface) {
- mSessionImpl.onSetSurface(surface);
+ void setSurface(Surface surface) {
+ onSetSurface(surface);
// TODO: Handle failure.
}
/**
- * Calls {@link TvInputSessionImpl#onSetVolume}.
+ * Calls {@link onSetVolume}.
*/
- @Override
- public final void setVolume(float volume) {
- mSessionImpl.onSetVolume(volume);
+ void setVolume(float volume) {
+ onSetVolume(volume);
}
/**
- * Calls {@link TvInputSessionImpl#onTune}.
+ * Calls {@link onTune}.
*/
- @Override
- public final void tune(Uri channelUri) {
- mSessionImpl.onTune(channelUri);
+ void tune(Uri channelUri) {
+ onTune(channelUri);
// TODO: Handle failure.
}
}
@@ -222,7 +205,7 @@
return;
}
ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
- new TvInputSessionImplInternal(sessionImpl));
+ sessionImpl);
cb.onSessionCreated(stub);
} catch (RemoteException e) {
Log.e(TAG, "error in onSessionCreated");
diff --git a/core/java/android/tv/TvInputSession.java b/core/java/android/tv/TvInputSession.java
deleted file mode 100644
index cdd363b..0000000
--- a/core/java/android/tv/TvInputSession.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2014 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.tv;
-
-import android.net.Uri;
-import android.view.Surface;
-
-/**
- * The TvInputSession provides the per-session functionality of TvInputService.
- */
-public abstract class TvInputSession {
- /**
- * This method is called when the application would like to stop using the current input
- * session.
- */
- public void release() { }
-
- /**
- * Sets the {@link Surface} for the current input session on which the TV input renders video.
- *
- * @param surface {@link Surface} to be used for the video playback of this session.
- */
- public void setSurface(Surface surface) { }
-
- /**
- * This method is called when the application needs to handle the change of audio focus by
- * setting the relative volume of the current TV input service session.
- *
- * @param volume Volume scale from 0.0 to 1.0.
- */
- // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
- // is to introduce some new concepts that will solve a number of problems in audio policy today.
- public void setVolume(float volume) { }
-
- /**
- * Tunes to a given channel.
- *
- * @param channelUri The URI of the channel.
- */
- public void tune(Uri channelUri) { }
-}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 80d5bf2..7d13399 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -236,6 +236,11 @@
boolean isSafeModeEnabled();
/**
+ * Enables the screen if all conditions are met.
+ */
+ void enableScreenIfNeeded();
+
+ /**
* Clears the frame statistics for a given window.
*
* @param token The window token.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index cbb98e1..1429837 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -67,7 +67,7 @@
void destroy(boolean full) {
mInitialized = false;
updateEnabledState(null);
- nDestroyCanvas(mNativeProxy);
+ nDestroyCanvasAndSurface(mNativeProxy);
}
private void updateEnabledState(Surface surface) {
@@ -300,7 +300,7 @@
private static native void nDrawDisplayList(long nativeProxy, long displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
- private static native void nDestroyCanvas(long nativeProxy);
+ private static native void nDestroyCanvasAndSurface(long nativeProxy);
private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d5a7d33..032a82f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -49,7 +49,7 @@
public interface WindowManager extends ViewManager {
/**
* Exception that is thrown when trying to add view whose
- * {@link WindowManager.LayoutParams} {@link WindowManager.LayoutParams#token}
+ * {@link LayoutParams} {@link LayoutParams#token}
* is invalid.
*/
public static class BadTokenException extends RuntimeException {
@@ -173,7 +173,6 @@
* @see #TYPE_SEARCH_BAR
* @see #TYPE_PHONE
* @see #TYPE_SYSTEM_ALERT
- * @see #TYPE_KEYGUARD
* @see #TYPE_TOAST
* @see #TYPE_SYSTEM_OVERLAY
* @see #TYPE_PRIORITY_PHONE
@@ -197,7 +196,6 @@
@ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
@ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT, to = "TYPE_SYSTEM_ALERT"),
- @ViewDebug.IntToString(from = TYPE_KEYGUARD, to = "TYPE_KEYGUARD"),
@ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
@ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
@@ -341,13 +339,13 @@
* In multiuser systems shows only on the owning user's window.
*/
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;
-
+
/**
* Window type: keyguard window.
* In multiuser systems shows on all users' windows.
*/
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;
-
+
/**
* Window type: transient notifications.
* In multiuser systems shows only on the owning user's window.
@@ -916,7 +914,6 @@
*/
public static final int FLAG_NEEDS_MENU_KEY = 0x40000000;
-
/**
* Various behavioral options/flags. Default is none.
*
@@ -1090,6 +1087,14 @@
public static final int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR = 0x00000200;
/**
+ * Flag whether the current window is a keyguard window, meaning that it will hide all other
+ * windows behind it except for windows with flag {@link #FLAG_SHOW_WHEN_LOCKED} set.
+ * Further, this can only be set by {@link LayoutParams#TYPE_STATUS_BAR}.
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_KEYGUARD = 0x00000400;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index e68d4c0..c9be54d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1005,6 +1005,14 @@
public void dismissKeyguardLw();
/**
+ * Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
+ * returns true as soon as we know that Keyguard is disabled.
+ *
+ * @return true if the keyguard has drawn.
+ */
+ public boolean isKeyguardDrawnLw();
+
+ /**
* Given an orientation constant, returns the appropriate surface rotation,
* taking into account sensors, docking mode, rotation lock, and other factors.
*
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
new file mode 100644
index 0000000..2f8850b
--- /dev/null
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 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.webkit;
+
+import android.net.Uri;
+
+/**
+ * This class wraps a permission request, and is used to request permission for
+ * the web content to access the resources.
+ *
+ * Either {@link #grant(long) grant()} or {@link #deny()} must be called to response the
+ * request, otherwise, {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will
+ * not be invoked again if there is other permission request in this WebView.
+ *
+ * @hide
+ */
+public interface PermissionRequest {
+ /**
+ * Resource belongs to geolocation service.
+ */
+ public final static long RESOURCE_GEOLOCATION = 1 << 0;
+ /**
+ * Resource belongs to video capture device, like camera.
+ */
+ public final static long RESOURCE_VIDEO_CAPTURE = 1 << 1;
+ /**
+ * Resource belongs to audio capture device, like microphone.
+ */
+ public final static long RESOURCE_AUDIO_CAPTURE = 1 << 2;
+
+ /**
+ * @return the origin of web content which attempt to access the restricted
+ * resources.
+ */
+ public Uri getOrigin();
+
+ /**
+ * @return a bit mask of resources the web content wants to access.
+ */
+ public long getResources();
+
+ /**
+ * Call this method to grant origin the permission to access the given resources.
+ * The granted permission is only valid for this WebView.
+ *
+ * @param resources the resources granted to be accessed by origin, to grant
+ * request, the requested resources returned by {@link #getResources()}
+ * must be equals or a subset of granted resources.
+ * This parameter is designed to avoid granting permission by accident
+ * especially when new resources are requested by web content.
+ * Calling grant(getResources()) has security issue, the new permission
+ * will be granted without being noticed.
+ */
+ public void grant(long resources);
+
+ /**
+ * Call this method to deny the request.
+ */
+ public void deny();
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index aa57423..60cba86 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -296,6 +296,30 @@
public void onGeolocationPermissionsHidePrompt() {}
/**
+ * Notify the host application that web content is requesting permission to
+ * access the specified resources and the permission currently isn't granted
+ * or denied. The host application must invoke {@link PermissionRequest#grant(long)}
+ * or {@link PermissionRequest#deny()}.
+ *
+ * If this method isn't overridden, the permission is denied.
+ *
+ * @param request the PermissionRequest from current web content.
+ * @hide
+ */
+ public void onPermissionRequest(PermissionRequest request) {
+ request.deny();
+ }
+
+ /**
+ * Notify the host application that the given permission request
+ * has been canceled. Any related UI should therefore be hidden.
+ *
+ * @param request the PermissionRequest need be canceled.
+ * @hide
+ */
+ public void onPermissionRequestCanceled(PermissionRequest request) {}
+
+ /**
* Tell the client that a JavaScript execution timeout has occured. And the
* client may decide whether or not to interrupt the execution. If the
* client returns true, the JavaScript will be interrupted. If the client
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 85168fd..62fbbc4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -25,6 +25,7 @@
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.net.http.SslCertificate;
import android.os.Build;
import android.os.Bundle;
@@ -1640,6 +1641,21 @@
}
/**
+ * Preauthorize the given origin to access resources.
+ * This authorization only valid for this WebView instance life cycle and
+ * will not retained.
+ *
+ * @param origin the origin authorized to access resources
+ * @param resources the resource authorized to be accessed by origin.
+ *
+ * @hide
+ */
+ public void preauthorizePermission(Uri origin, long resources) {
+ checkThread();
+ mProvider.preauthorizePermission(origin, resources);
+ }
+
+ /**
* Sets the Picture listener. This is an interface used to receive
* notifications of a new Picture.
*
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 696aad4..9488cdd 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -23,6 +23,7 @@
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.net.http.SslCertificate;
import android.os.Bundle;
import android.os.Message;
@@ -245,6 +246,8 @@
public View findHierarchyView(String className, int hashCode);
+ public void preauthorizePermission(Uri origin, long resources);
+
//-------------------------------------------------------------------------
// Provider internal methods
//-------------------------------------------------------------------------
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 96a2ab5..301317e 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -7167,7 +7167,7 @@
final int itemCount = getCount();
final int clampedPosition = MathUtils.constrain(targetPosition, 0, itemCount - 1);
- final int clampedBoundPosition = MathUtils.constrain(boundPosition, 0, itemCount - 1);
+ final int clampedBoundPosition = MathUtils.constrain(boundPosition, -1, itemCount - 1);
final int firstPosition = getFirstVisiblePosition();
final int lastPosition = firstPosition + getChildCount();
final int targetRow = getRowForPosition(clampedPosition);
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 64a1574..cde8080 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -161,9 +161,11 @@
@Override
public View onCreateActionView() {
// Create the view and set its data model.
- ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
- activityChooserView.setActivityChooserModel(dataModel);
+ if (!activityChooserView.isInEditMode()) {
+ ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
+ activityChooserView.setActivityChooserModel(dataModel);
+ }
// Lookup and set the expand action icon.
TypedValue outTypedValue = new TypedValue();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5e4c143..a7278da 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -714,19 +714,19 @@
break;
case com.android.internal.R.styleable.TextAppearance_shadowColor:
- shadowcolor = a.getInt(attr, 0);
+ shadowcolor = appearance.getInt(attr, 0);
break;
case com.android.internal.R.styleable.TextAppearance_shadowDx:
- dx = a.getFloat(attr, 0);
+ dx = appearance.getFloat(attr, 0);
break;
case com.android.internal.R.styleable.TextAppearance_shadowDy:
- dy = a.getFloat(attr, 0);
+ dy = appearance.getFloat(attr, 0);
break;
case com.android.internal.R.styleable.TextAppearance_shadowRadius:
- r = a.getFloat(attr, 0);
+ r = appearance.getFloat(attr, 0);
break;
}
}
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index c6afae0..fb93ddd 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -170,6 +170,15 @@
init(dialog.getWindow().getDecorView());
}
+ /**
+ * Only for edit mode.
+ * @hide
+ */
+ public WindowDecorActionBar(View layout) {
+ assert layout.isInEditMode();
+ init(layout);
+ }
+
private void init(View decor) {
mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
com.android.internal.R.id.action_bar_overlay_layout);
@@ -559,8 +568,8 @@
return;
}
- final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
- .disallowAddToBackStack();
+ final FragmentTransaction trans = mActionView.isInEditMode() ? null :
+ mActivity.getFragmentManager().beginTransaction().disallowAddToBackStack();
if (mSelectedTab == tab) {
if (mSelectedTab != null) {
@@ -578,7 +587,7 @@
}
}
- if (!trans.isEmpty()) {
+ if (trans != null && !trans.isEmpty()) {
trans.commit();
}
}
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 63ff5a0..b78c70f 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -25,12 +25,24 @@
interface IKeyguardService {
boolean isShowing();
boolean isSecure();
- boolean isShowingAndNotHidden();
+ boolean isShowingAndNotOccluded();
boolean isInputRestricted();
boolean isDismissable();
oneway void verifyUnlock(IKeyguardExitCallback callback);
oneway void keyguardDone(boolean authenticated, boolean wakeup);
- oneway void setHidden(boolean isHidden);
+
+ /**
+ * Sets the Keyguard as occluded when a window dismisses the Keyguard with flag
+ * FLAG_SHOW_ON_LOCK_SCREEN.
+ *
+ * @param isOccluded Whether the Keyguard is occluded by another window.
+ * @return See IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_*. This is needed because
+ * PhoneWindowManager needs to set these flags immediately and can't wait for the
+ * Keyguard thread to pick it up. In the hidden case, PhoneWindowManager is solely
+ * responsible to make sure that the flags are unset.
+ */
+ int setOccluded(boolean isOccluded);
+
oneway void dismiss();
oneway void onDreamingStarted();
oneway void onDreamingStopped();
diff --git a/core/java/com/android/internal/policy/IKeyguardServiceConstants.java b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
new file mode 100644
index 0000000..b88174a
--- /dev/null
+++ b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+/**
+ * @hide
+ */
+public class IKeyguardServiceConstants {
+
+ /**
+ * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+ * Don't change the keyguard window flags.
+ */
+ public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE = 0;
+
+ /**
+ * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+ * Set the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
+ */
+ public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS = 1;
+
+ /**
+ * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+ * Unset the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
+ */
+ public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS = 2;
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index dfdb9ae..6428e15 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -47,6 +47,8 @@
int uid, int initialPid, String message, int userId);
void onClearAllNotifications(int userId);
void onNotificationClear(String pkg, String tag, int id, int userId);
+ void onNotificationVisibilityChanged(
+ in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys);
void setSystemUiVisibility(int vis, int mask);
void setHardKeyboardEnabled(boolean enabled);
void toggleRecentApps();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 4504910..2882b54 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -788,13 +788,13 @@
*/
public int getKeyguardStoredPasswordQuality() {
int quality =
- (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
// If the user has chosen to use weak biometric sensor, then return the backup locking
// method and treat biometric as a special case.
if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
quality =
(int) getLong(PASSWORD_TYPE_ALTERNATE_KEY,
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
}
return quality;
}
@@ -804,7 +804,7 @@
*/
public boolean usingBiometricWeak() {
int quality =
- (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
}
@@ -943,11 +943,12 @@
*/
public boolean isLockPatternEnabled() {
final boolean backupEnabled =
- getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
- == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ getLong(PASSWORD_TYPE_ALTERNATE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+ == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
- && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
+ && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
(usingBiometricWeak() && backupEnabled));
}
diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
index 961e471..5f3c5f9 100644
--- a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
+++ b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
@@ -107,8 +107,6 @@
}
if (background instanceof ColorDrawable) {
mModestyPanel.setBackgroundDrawable(background);
- } else {
- mModestyPanel.setBackgroundColor(Color.BLACK);
}
SizeAdaptiveLayout.LayoutParams layout =
new SizeAdaptiveLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index 6ae6c8f..d0269a3 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -146,8 +146,8 @@
jlong renderNodePtr) {
using namespace android::uirenderer;
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- TreeInfo info = {0};
- renderNode->prepareTree(info);
+ TreeInfo ignoredInfo;
+ renderNode->prepareTree(ignoredInfo);
}
static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 2eb0d78..b2f17de 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -127,8 +127,8 @@
static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz,
jlong layerUpdaterPtr) {
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
- bool ignoredHasFunctors;
- return layer->apply(&ignoredHasFunctors);
+ TreeInfo ignoredInfo;
+ return layer->apply(ignoredInfo);
}
static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 30d3e0c..b5f489d 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -121,10 +121,10 @@
proxy->drawDisplayList(displayList, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
}
-static void android_view_ThreadedRenderer_destroyCanvas(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->destroyCanvas();
+ proxy->destroyCanvasAndSurface();
}
static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
@@ -194,7 +194,7 @@
{ "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
{ "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
{ "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList },
- { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
+ { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
{ "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b2709af..606a4b1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -234,6 +234,7 @@
<protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
<protected-broadcast
android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
+ <protected-broadcast android:name="android.net.scoring.SCORE_NETWORKS" />
<protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE" />
<protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE" />
<protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
@@ -762,6 +763,13 @@
android:description="@string/permdesc_changeWimaxState"
android:label="@string/permlab_changeWimaxState" />
+ <!-- Allows applications to act as network scorers. @hide -->
+ <permission android:name="android.permission.SCORE_NETWORKS"
+ android:permissionGroup="android.permission-group.NETWORK"
+ android:protectionLevel="normal"
+ android:description="@string/permdesc_scoreNetworks"
+ android:label="@string/permlab_scoreNetworks" />
+
<!-- ======================================= -->
<!-- Permissions for short range, peripheral networks -->
<!-- ======================================= -->
@@ -2290,6 +2298,13 @@
android:description="@string/permdesc_broadcastWapPush"
android:protectionLevel="signature" />
+ <!-- Allows an application to broadcast a SCORE_NETWORKS request.
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.BROADCAST_SCORE_NETWORKS"
+ android:label="@string/permlab_broadcastScoreNetworks"
+ android:description="@string/permdesc_broadcastScoreNetworks"
+ android:protectionLevel="signature|system" />
+
<!-- Not for use by third-party applications. -->
<permission android:name="android.permission.MASTER_CLEAR"
android:label="@string/permlab_masterClear"
diff --git a/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..3813563
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..47263ea
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..aa23c59
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..cac32b5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..25b8935
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..598b98c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..df2fdb8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..79fe7c5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..7bcebcd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..eb1d945
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..d43e4d1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..42ac8ca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..b5f6176
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..9137fea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..3f1eee3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..506a186
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..e54d32e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..fb0e926
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..ef4ebc0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..9ddbcf5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..ddacb59
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..c10a1b7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..bd80981
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..513ee8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..c1c23d04
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..38b8e8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..c1ca323
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..d6002a7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..1a2546f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..500ec33
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..21ed9144
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..fc1b8b4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..8e1ab5b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..81b13aa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..d95f1d0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..93469a2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..5753d89
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..b3493e7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..cd5b00f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..5ee867c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_check_quantum_anim.xml b/core/res/res/drawable/btn_check_quantum_anim.xml
new file mode 100644
index 0000000..d68d512
--- /dev/null
+++ b/core/res/res/drawable/btn_check_quantum_anim.xml
@@ -0,0 +1,79 @@
+<!-- Copyright (C) 2014 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:trigger="state_checked"
+ android:versionCode="1" >
+
+ <size
+ android:height="32dp"
+ android:width="32dp" />
+
+ <viewport
+ android:viewportHeight="320"
+ android:viewportWidth="320" />
+
+ <group>
+ <path
+ android:name="check"
+ android:pathData="M 232.1,80.6 L 248.5,92.1 L 145.2,239.5 L 71.5,187.8 L 83,171.5 L 140.3,211.7 z"
+ android:fill="?attr/colorControlActivated" />
+ </group>
+ <group>
+ <path
+ android:name="box1"
+ android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
+ android:fill="?attr/colorControlActivated"
+ android:stroke="?attr/colorControlActivated"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
+ </group>
+ <group>
+ <path
+ android:name="box2"
+ android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
+ android:rotation="-35"
+ android:pivotX="140"
+ android:pivotY="220"
+ android:fill="?attr/colorControlNormal"
+ android:stroke="?attr/colorControlNormal"
+ android:strokeWidth="5"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
+ </group>
+ <group>
+ <path
+ android:name="box3"
+ android:pathData="M 160,200 L 160,240 L 120,240 L 120,200 L 160,200 L 160,200 z"
+ android:stroke="?attr/colorControlNormal"
+ android:strokeWidth="10"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
+ </group>
+ <group>
+ <path
+ android:name="box4"
+ android:pathData="M 240,80 L 240,240 L 80,240 L 80,80 L 240,80 L 240,80 z"
+ android:stroke="?attr/colorControlNormal"
+ android:strokeWidth="20"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
+ </group>
+
+ <animation
+ android:durations="300,100,0,300"
+ android:sequence="check,box1,box2,box3,box4" />
+
+</vector>
diff --git a/core/res/res/drawable/ic_clear_quantum.xml b/core/res/res/drawable/ic_clear_quantum.xml
new file mode 100644
index 0000000..02f0929
--- /dev/null
+++ b/core/res/res/drawable/ic_clear_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_clear_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_commit_search_api_quantum.xml b/core/res/res/drawable/ic_commit_search_api_quantum.xml
new file mode 100644
index 0000000..02d08b9
--- /dev/null
+++ b/core/res/res/drawable/ic_commit_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_commit_search_api_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_go_search_api_quantum.xml b/core/res/res/drawable/ic_go_search_api_quantum.xml
new file mode 100644
index 0000000..b5b5cfb
--- /dev/null
+++ b/core/res/res/drawable/ic_go_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_go_search_api_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_search_api_quantum.xml b/core/res/res/drawable/ic_search_api_quantum.xml
new file mode 100644
index 0000000..2bbc294
--- /dev/null
+++ b/core/res/res/drawable/ic_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_search_api_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_voice_search_api_quantum.xml b/core/res/res/drawable/ic_voice_search_api_quantum.xml
new file mode 100644
index 0000000..ddb14ef
--- /dev/null
+++ b/core/res/res/drawable/ic_voice_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_voice_search_api_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_bg_dim.xml
similarity index 77%
rename from core/res/res/drawable/notification_quantum_background.xml
rename to core/res/res/drawable/notification_bg_dim.xml
index 7b508a9..ec20368 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_bg_dim.xml
@@ -15,7 +15,9 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#ffffffff" />
- <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
-</shape>
\ No newline at end of file
+<touch-feedback
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:tint="#ff444444"
+ >
+ <item android:drawable="@drawable/notification_bg_normal" />
+</touch-feedback>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml
index 608115e..300a565 100644
--- a/core/res/res/drawable/notification_quantum_bg.xml
+++ b/core/res/res/drawable/notification_quantum_bg.xml
@@ -16,6 +16,16 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@drawable/notification_quantum_press" />
- <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" />
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#ffd0d0d0" />
+ <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+ </shape>
+ </item>
+ <item>
+ <shape>
+ <solid android:color="#fffafafa" />
+ <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+ </shape>
+ </item>
</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_bg_dim.xml
similarity index 65%
copy from core/res/res/drawable/notification_quantum_background.xml
copy to core/res/res/drawable/notification_quantum_bg_dim.xml
index 7b508a9..ab0e049 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_quantum_bg_dim.xml
@@ -15,7 +15,15 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#ffffffff" />
- <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
-</shape>
\ No newline at end of file
+<touch-feedback
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:tint="#ffffffff"
+ android:tintMode="src_over"
+ >
+ <item>
+ <shape>
+ <solid android:color="#d4ffffff" />
+ <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+ </shape>
+ </item>
+</touch-feedback>
\ No newline at end of file
diff --git a/core/res/res/drawable/text_select_handle_left_quantum.xml b/core/res/res/drawable/text_select_handle_left_quantum.xml
new file mode 100644
index 0000000..a0ad7cf
--- /dev/null
+++ b/core/res/res/drawable/text_select_handle_left_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/text_select_handle_left_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/text_select_handle_middle_quantum.xml b/core/res/res/drawable/text_select_handle_middle_quantum.xml
new file mode 100644
index 0000000..bff0b66
--- /dev/null
+++ b/core/res/res/drawable/text_select_handle_middle_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/text_select_handle_middle_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/text_select_handle_right_quantum.xml b/core/res/res/drawable/text_select_handle_right_quantum.xml
new file mode 100644
index 0000000..413661f
--- /dev/null
+++ b/core/res/res/drawable/text_select_handle_right_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/text_select_handle_right_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/textfield_search_quantum.xml b/core/res/res/drawable/textfield_search_quantum.xml
new file mode 100644
index 0000000..877de46
--- /dev/null
+++ b/core/res/res/drawable/textfield_search_quantum.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_window_focused="false" android:state_enabled="true">
+ <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_window_focused="false" android:state_enabled="false">
+ <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_enabled="true" android:state_focused="true">
+ <nine-patch android:src="@drawable/textfield_search_activated_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:state_enabled="true" android:state_activated="true">
+ <nine-patch android:src="@drawable/textfield_search_activated_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:state_enabled="true">
+ <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item>
+ <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+</selector>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/fast_out_linear_in.xml
similarity index 77%
rename from core/res/res/drawable/notification_quantum_press.xml
rename to core/res/res/interpolator/fast_out_linear_in.xml
index 4999f55..19f95a6 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/fast_out_linear_in.xml
@@ -15,7 +15,8 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#ffcccccc" />
- <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.4"
+ android:controlY1="0"
+ android:controlX2="1"
+ android:controlY2="1"/>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/fast_out_slow_in.xml
similarity index 77%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to core/res/res/interpolator/fast_out_slow_in.xml
index 4999f55..2d68dbb 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/fast_out_slow_in.xml
@@ -15,7 +15,8 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#ffcccccc" />
- <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.4"
+ android:controlY1="0"
+ android:controlX2="0.2"
+ android:controlY2="1"/>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/linear_out_slow_in.xml
similarity index 77%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to core/res/res/interpolator/linear_out_slow_in.xml
index 4999f55..83fc223 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/linear_out_slow_in.xml
@@ -15,7 +15,8 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#ffcccccc" />
- <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0"
+ android:controlY1="0"
+ android:controlX2="0.2"
+ android:controlY2="1"/>
diff --git a/core/res/res/layout/action_bar_home_quantum.xml b/core/res/res/layout/action_bar_home_quantum.xml
new file mode 100644
index 0000000..9213458
--- /dev/null
+++ b/core/res/res/layout/action_bar_home_quantum.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.internal.widget.ActionBarView$HomeView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start">
+ <ImageView android:id="@android:id/up"
+ android:src="?android:attr/homeAsUpIndicator"
+ android:layout_gravity="center_vertical|start"
+ android:visibility="gone"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:scaleType="centerInside" />
+ <ImageView android:id="@android:id/home"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dip"
+ android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
+ android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
+ android:adjustViewBounds="true"
+ android:scaleType="fitCenter" />
+</view>
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
index 8863cfa..8f3019d 100644
--- a/core/res/res/layout/notification_template_quantum_base.xml
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -17,7 +17,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:background="@android:drawable/notification_quantum_bg"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="64dp"
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
index 63935bb..45e69b1 100644
--- a/core/res/res/layout/notification_template_quantum_big_base.xml
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -17,7 +17,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:background="@android:drawable/notification_quantum_bg"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml
index e49c3bd..f68e414 100644
--- a/core/res/res/layout/notification_template_quantum_big_picture.xml
+++ b/core/res/res/layout/notification_template_quantum_big_picture.xml
@@ -17,7 +17,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:background="@android:drawable/notification_quantum_bg"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
index 516b0c4..f7769d7 100644
--- a/core/res/res/layout/notification_template_quantum_big_text.xml
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -16,7 +16,6 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:background="@android:drawable/notification_quantum_bg"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
index c6192be..04974c4 100644
--- a/core/res/res/layout/notification_template_quantum_inbox.xml
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -18,7 +18,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
- android:background="@android:drawable/notification_quantum_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
internal:layout_minHeight="65dp"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 88f5c54..f9b00a9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n legstuk-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Laat die houer toe om bedoelings na \'n toesteladministrateur te stuur. Dit moet nooit vir normale programme nodig wees nie."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind aan \'n TV-invoer"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Laat die houer toe om aan die topvlak-koppelvlak van \'n TV-invoer te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"voeg \'n toesteladministrateur by of verwyder een"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Laat die houer aktiewe toesteladministrateurs byvoeg of verwyder. Behoort nooit nodig te wees vir normale programme nie."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"verander skermoriëntasie"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 101c4dc..c6ff2da 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الأداة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"التفاعل مع مشرف الجهاز"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"للسماح للمالك بإرسال الأهداف إلى أحد مشرفي الجهاز. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"الالتزام بإدخال التلفزيون"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لإدخال التلفزيون. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"إضافة مشرف جهاز أو إزالته"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"للسماح بحامل البطاقة بإضافة مشرفي أجهزة نشطين أو إزالتهم. لا يلزم ذلك أبدًا للتطبيقات العادية."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"تغيير اتجاه الشاشة"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 1d063f6..618eba9 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar amb un administrador del dispositiu"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet que el titular enviï intents a un administrador del sistema. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"Vinculació a una entrada de televisor"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permet que el titular es vinculi a la interfície de nivell superior d\'una entrada de televisor. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"afegeix un administrador al dispositiu o suprimeix-lo"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet que el titular afegeixi administradors actius al dispositiu o en suprimeixi. No s\'hauria de necessitar per a les aplicacions normals."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"canviar l\'orientació de la pantalla"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 3c113f0..73913a2 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Tillader, at brugeren kan forpligte sig til en grænseflade for en widgettjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillader, at brugeren kan sende hensigter til en enhedsadministrator. Dette bør aldrig være nødvendigt for almindelige apps."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"knyt til en tv-indgang"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Giver indehaveren mulighed for at knytte sig til det øverste grænsefladeniveau for en tv-indgang. Dette bør ikke være nødvendigt i normale apps."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"tilføje eller fjerne en enhedsadministrator"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillader, at man tilføjer eller fjerner aktive enhedsadministratorer. Dette burde aldrig være nødvendigt til normale apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"skift skærmretning"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e1e9106..456b56d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας γραφικών στοιχείων. Δεν απαιτείται για κανονικές εφαρμογές."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"επικοινωνία με έναν διαχειριστή συσκευής"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Επιτρέπει στον κάτοχο την αποστολή στόχων σε έναν διαχειριστή συσκευής. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"σύνδεση σε μία είσοδο τηλεόρασης"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανώτερου επιπέδου μιας εισόδου τηλεόρασης. Δεν απαιτείται ποτέ για τις συνηθισμένες εφαρμογές."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"προσθήκη ή κατάργηση ενός διαχειριστή συσκευής"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Επιτρέπει στον κάτοχο να προσθέτει ή να καταργεί ενεργούς διαχειριστές συσκευών. Δεν θα πρέπει να ζητείται ποτέ για κανονικές εφαρμογές."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"αλλαγή προσανατολισμού οθόνης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8da35f1..528c840 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Allows the holder to bind to the top-level interface of a TV input. Should never be needed for normal apps."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8da35f1..528c840 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Allows the holder to bind to the top-level interface of a TV input. Should never be needed for normal apps."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index adb033f..38774d7 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lubab omanikul siduda vidina teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"seadme administraatoriga suhtlemine"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Võimaldab omanikul saata kavatsusi seadme administraatorile. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"sidumine TV-sisendiga"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lubab omanikul siduda TV-sisendi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"seadme administraatori lisamine või eemaldamine"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Võimaldab omanikul lisada või eemaldada aktiivseid seadme administraatoreid. Tavarakenduste puhul ei tohiks see kunagi vajalik olla."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"muuda ekraani paigutust"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1419bc4..4a1c409 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्यवस्थापक के साथ सहभागिता करें"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"धारक को किसी उपकरण व्यवस्थापक को उद्देश्य भेजने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"टीवी इनपुट से आबद्ध करें"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"धारक को किसी टीवी इनपुट के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"उपकरण उपकरण सुचारू ढ़ंग से चलाने वाले को जोड़ें या निकालें"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"धारक को सक्रिय डिवाइस व्यवस्थापकों को जोड़ने या निकालने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"स्क्रीन अभिविन्यास बदलें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index dde0a5b..10e4ac8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge widgeta. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s administratorom uređaja"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Nositelju omogućuje slanje namjera administratoru uređaja. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"povezivanje s TV ulazom"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Nositelju omogućuje vezanje uz sučelje najviše razine TV ulaza. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodavanje ili uklanjanje administratora uređaja"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Omogućuje nositelju dodavanje ili uklanjanje administratora aktivnih uređaja. Nikada ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"promjena orijentacije zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 41a1fb9..fd3a887 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lehetővé teszi a használó számára, hogy csatlakozzon egy modulszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"az eszközkezelő használata"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lehetővé teszi a tulajdonos számára, hogy célokat küldjön egy eszközkezelőnek. A normál alkalmazásoknak erre soha nincs szüksége."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"csatlakozás tévébemenethez"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lehetővé teszi, hogy a tulajdonos kapcsolódjon egy tévébemenet legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"eszközrendszergazda hozzáadása vagy eltávolítása"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Lehetővé teszi a tulajdonos számára, hogy aktív eszközrendszergazdákat adjon meg vagy távolítson el. A normál alkalmazásoknál erre soha nincs szükség."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"képernyő irányának módosítása"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b1d94e6..eddb9c85 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan widget. Tidak pernah diperlukan oleh apl normal."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan admin perangkat"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Mengizinkan pemegang mengirimkan tujuan kepada administrator perangkat. Tidak pernah diperlukan oleh apl normal."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"mengikat ke masukan TV"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Memungkinkan pemegang mengikat ke antarmuka tingkat tinggi dari masukan TV. Tidak pernah diperlukan oleh aplikasi normal."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"menambah atau menghapus admin perangkat"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Memungkinkan pemegang menambahkan atau menghapus administrator perangkat aktif. Tidak pernah dibutuhkan oleh aplikasi normal."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ubah orientasi layar"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 222dfe3..43b94b7 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של שירות Widget. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"קיים אינטראקציה עם מנהל המכשיר"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"מאפשר למשתמש לשלוח כוונות למנהל התקנים. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"איגוד לקלט טלוויזיה"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"הרשאה זו מאפשרת למחזיק בה לבצע איגוד לממשק הרמה העליונה של קלט טלוויזיה. הרשאה זו אף פעם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"הוספה או הסרה של מנהלי מכשיר"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"מאפשרת לבעלים להוסיף או להסיר מנהלי מכשיר פעילים. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"שנה את כיוון המסך"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 8dbd6ac..cb4f257 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មធាតុក្រាហ្វិក។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ទាក់ទងជាមួយអ្នកគ្រប់គ្រងឧបករណ៍"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យម្ចាស់ផ្ញើគោលបំណងទៅអ្នកគ្រប់គ្រងឧបករណ៍។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់ទៅការបញ្ចូលទូរទស្សន៍"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតខ្ពស់នៃការបញ្ចូលទូរទស្សន៍។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាតឲ្យម្ចាស់បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍សកម្មចេញ។ មិនគួរប្រើសម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរទិសអេក្រង់"</string>
diff --git a/core/res/res/values-land/dimens_quantum.xml b/core/res/res/values-land/dimens_quantum.xml
new file mode 100644
index 0000000..7789219
--- /dev/null
+++ b/core/res/res/values-land/dimens_quantum.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<resources>
+
+ <!-- Default height of an action bar. -->
+ <dimen name="action_bar_default_height_quantum">48dp</dimen>
+ <!-- Default padding of an action bar. -->
+ <dimen name="action_bar_default_padding_quantum">0dp</dimen>
+
+</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 79b8a33..178176f 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບອິນເຕີເຟດລະດັບສູງສຸດ ຂອງບໍລິການວິເຈັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ຕິດຕໍ່ກັບຜູ່ເບິ່ງແຍງອຸປະກອນ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສົ່ງເຈດຕະນາຫາຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"ຜູກກັບການປ້ອນຂໍ້ມູນເຂົ້າໂທລະທັດ"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກຕິດກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດຂອງການປ້ອນຂໍ້ມູນເຂົ້າໂທລະທັດ. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ເພີ່ມ ຫຼືລຶບຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສາມາດລຶບ ຫຼືລຶບຂໍ້ມູນອຸປະກອນທີ່ນຳໃຊ້ໄດ້. ແອັບຯທົ່ວໄປບໍ່ຈຳເປັນຕ້ອງໃຊ້."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ປ່ຽນລວງຂອງໜ້າຈໍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 99184d2..69d2420 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Leidžiama savininkui susisaistyti su aukščiausio lygio valdiklio paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"sąveikauti su įrenginio administratoriumi"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Leidžiama savininkui siųsti tikslus įrenginio administratoriui. Įprastoms programoms to neturėtų prireikti."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"susisaistyti su TV įvestimi"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Leidžiama savininkui susisaistyti su aukščiausio lygio TV įvesties sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridėti arba pašalinti įrenginio administratorių"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Savininkui leidžiama pridėti aktyvių įrenginio administratorių arba juos pašalinti. Neturėtų reikėti įprastoms programoms."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"keisti ekrano padėtį"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 433115c..965e3eb 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ļauj īpašniekam izveidot saiti ar logrīka pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"mijiedarboties ar ierīces administratoru"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ļauj īpašniekam nosūtīt informāciju par nodomiem ierīces administratoram. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"Izveidot saiti ar TV ieeju"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ļauj īpašniekam izveidot saiti ar TV ieejas augšējā līmeņa saskarni. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pievienot vai noņemt ierīces administratoru"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ļauj īpašniekam pievienot vai noņemt aktīvos ierīces administratorus. Nekad nav nepieciešama parastām lietotnēm."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"mainīt ekrāna orientāciju"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 442b856..1284d92 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Эзэмшигч нь виджет үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"төхөөрөмжийн админтай харилцан үйлчлэх"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Эзэмшигч нь төхөөрөмжийн админруу интент илгээх боломжтой. Энгийн апп-д шаардлагагүй."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"ТВ оролт холбох"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Эзэмшигч нь ТВ оролтын дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"төхөөрөмжийн админ нэмэх, хасах"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Эзэмшигч нь идэвхтэй төхөөрөмжийн администраторыг нэмэх, хасах боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"дэлгэцний чиглэлийг солих"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 379e3dd..65595ab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o titular vincule a interface de nível superior de um serviço de widget. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com um administrador do dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite ao titular enviar intenções para um administrador do aparelho. Nunca deverá ser necessário para aplicações normais."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"vincular a uma entrada de TV"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite ao titular vincular à interface de nível superior de uma entrada de TV. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adicionar ou remover um administrador de dispositivos"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite que o titular adicione ou remova administradores de dispositivos ativos. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"mudar orientação do ecrã"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index aa467bb..851addc 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby miniaplikácií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovať so správcom zariadenia"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteľovi odosielať informácie správcovi zariadenia. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"viazanie na televízny vstup"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania televízneho vstupu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridanie alebo odstránenie správcu zariadenia"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Umožňuje držiteľovi pridať alebo odstrániť správcov aktívnych zariadení. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"zmena orientácie obrazovky"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 0fed1e3..10d5376 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозвољава власнику да се обавеже на интерфејс услуге виџета највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"интеракција са администратором уређаја"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Омогућава да власник шаље своје намере администратору уређаја. Уобичајене апликације никада не би требало да је користе."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"повезивање са ТВ улазом"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Дозвољава власнику да се повеже са интерфејсом ТВ улаза највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавање или уклањање администратора уређаја"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозвољава власнику да додаје или уклања активне администраторе уређаја. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"промена положаја екрана"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 5afc0cd..820764c 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en widget. Ska inte behövas för vanliga appar."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"arbeta med en enhetsadministratör"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillåter att innehavaren skickar avsikter till en enhetsadministratör. Vanliga appar behöver aldrig göra detta."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"binda till en tv-insignal"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en tv-insignal. Ska inte behövas för vanliga appar."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"lägga till eller ta bort en enhetsadministratör"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Innehavaren får lägga till eller ta bort aktiva enhetsadministratörer. Detta ska normalt inte behövas för vanliga appar."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ändra bildskärmens rikting"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e31392e..6758319 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби віджетів. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаємодіяти з адмін. пристрою"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Дозволяє власнику надсилати задавані функції адміністратору пристрою. Ніколи не застосовується для звичайних програм."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"прив’язуватися до вводу телевізора"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня вводу телевізора. Ніколи не застосовується для звичайних додатків."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавати чи вилучати адміністраторів пристрою"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозволяє власнику додавати чи вилучати активних адміністраторів пристрою. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"змінювати орієнтацію екрана"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index fa499d9..45f1856 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (不建議一般應用程式使用)。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (不建議一般應用程式使用)。"</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"繫結至電視訊號輸入裝置"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"允許應用程式繫結至電視訊號輸入裝置的頂層介面,但一般應用程式並不需要使用。"</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (不建議一般應用程式使用)。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕瀏覽方向"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1359dd9..ccaf14c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -384,10 +384,8 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lensizakalo yesinqunjwana. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"xhumana nomphathi wedivaysi"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ivumela ummeli ukuthumela okuqukethwe kumphathi wedivaysi. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
- <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
- <skip />
- <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
- <skip />
+ <string name="permlab_bindTvInput" msgid="5601264742478168987">"bophezela kokokufaka kwe-TV"</string>
+ <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ivumela umbambi ukuthi abophezele uxhumano nomsebenzisi kwezinga eliphezulu lokokufaka kwe-TV. Akumele kudingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"engeza noma susa umlawuli wedivayisi"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ivumela umnikazi ukuthi angeze noma asuse abalawuli bedivayisi esebenzayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"shintsha ukujikeleza kwesikrini"</string>
diff --git a/core/res/res/values/dimens_quantum.xml b/core/res/res/values/dimens_quantum.xml
index 3913752..02e61e2 100644
--- a/core/res/res/values/dimens_quantum.xml
+++ b/core/res/res/values/dimens_quantum.xml
@@ -17,6 +17,8 @@
<!-- Default height of an action bar. -->
<dimen name="action_bar_default_height_quantum">56dp</dimen>
+ <!-- Default padding of an action bar. -->
+ <dimen name="action_bar_default_padding_quantum">4dp</dimen>
<!-- Vertical padding around action bar icons. -->
<dimen name="action_bar_icon_vertical_padding_quantum">16dp</dimen>
<!-- Text size for action bar titles -->
@@ -28,6 +30,10 @@
<!-- Bottom margin for action bar subtitles -->
<dimen name="action_bar_subtitle_bottom_margin_quantum">5dp</dimen>
+ <dimen name="action_button_min_width_quantum">48dp</dimen>
+ <dimen name="action_button_min_height_quantum">48dp</dimen>
+ <dimen name="action_overflow_min_width_quantum">36dp</dimen>
+
<dimen name="text_size_display_4_quantum">112sp</dimen>
<dimen name="text_size_display_3_quantum">56sp</dimen>
<dimen name="text_size_display_2_quantum">45sp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d3bee28..32b674e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2149,6 +2149,10 @@
<public type="attr" name="slideEdge" />
<public type="attr" name="actionBarTheme" />
<public type="attr" name="textAppearanceListItemSecondary" />
+ <public type="attr" name="colorPrimaryLight" />
+ <public type="attr" name="colorPrimary" />
+ <public type="attr" name="colorPrimaryDark" />
+ <public type="attr" name="colorAccent" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
@@ -2378,4 +2382,11 @@
<public type="style" name="TextAppearance.Quantum.Button" />
<public type="style" name="Widget.Holo.Light.Button.Borderless" />
+
+ <!-- An interpolator which accelerates fast but decelerates slowly. -->
+ <public type="interpolator" name="fast_out_slow_in" />
+ <!-- An interpolator which starts with a peak non-zero velocity and decelerates slowly. -->
+ <public type="interpolator" name="linear_out_slow_in" />
+ <!-- An interpolator which accelerates fast and keeps accelerating until the end. -->
+ <public type="interpolator" name="fast_out_linear_in" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fde5e3f..b0e1150 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -278,6 +278,8 @@
<!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
<string name="low_memory" product="tablet">Tablet storage is full. Delete some files to free space.</string>
<!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
+ <string name="low_memory" product="watch">Watch storage is full. Delete some files to free space.</string>
+ <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
<string name="low_memory" product="default">Phone storage is full. Delete some files to free space.</string>
<!-- SSL CA cert notification --> <skip />
@@ -324,6 +326,9 @@
<!-- Shutdown Confirmation Dialog. When the user chooses to power off the phone, there will
be a confirmation dialog. This is the message. -->
<string name="shutdown_confirm" product="tablet">Your tablet will shut down.</string>
+ <!-- Shutdown Confirmation Dialog. When the user chooses to power off the watch, there will
+ be a confirmation dialog. This is the message. -->
+ <string name="shutdown_confirm" product="watch">Your watch will shut down.</string>
<!-- Shutdown Confirmation Dialog. When the user chooses to power off the phone, there will
be a confirmation dialog. This is the message. -->
<string name="shutdown_confirm" product="default">Your phone will shut down.</string>
@@ -901,6 +906,14 @@
silently replace the content of any webpage with malicious variants.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_broadcastScoreNetworks">send score networks broadcast</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_broadcastScoreNetworks">Allows the app
+ to broadcast a notification that networks need to be scored.
+ Never needed for normal apps.
+ </string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_setProcessLimit">limit number of running processes</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_setProcessLimit">Allows the app
@@ -1876,6 +1889,15 @@
connect the phone to and disconnect the phone from WiMAX networks.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_scoreNetworks">score networks</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_scoreNetworks" product="tablet">Allows the app to
+ rank networks and influence which networks the tablet should prefer.</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_scoreNetworks" product="default">Allows the app to
+ rank networks and influence which networks the phone should prefer.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_bluetooth">pair with Bluetooth devices</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetooth" product="tablet">Allows the app to view the
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 2720d61..e42703e 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -713,10 +713,9 @@
<style name="Widget.Quantum.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
<style name="Widget.Quantum.ActionButton" parent="Widget.ActionButton">
- <item name="minWidth">@dimen/action_button_min_width</item>
+ <item name="minWidth">@dimen/action_button_min_width_quantum</item>
+ <item name="minHeight">@dimen/action_button_min_height_quantum</item>
<item name="gravity">center</item>
- <item name="paddingStart">12dip</item>
- <item name="paddingEnd">12dip</item>
<item name="scaleType">center</item>
<item name="maxLines">2</item>
</style>
@@ -729,6 +728,9 @@
<item name="src">@drawable/ic_menu_moreoverflow_quantum</item>
<item name="background">?attr/actionBarItemBackground</item>
<item name="contentDescription">@string/action_menu_overflow_description</item>
+ <item name="minWidth">@dimen/action_overflow_min_width_quantum</item>
+ <item name="minHeight">@dimen/action_button_min_height_quantum</item>
+ <item name="scaleType">center</item>
</style>
<style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar"/>
@@ -756,16 +758,19 @@
</style>
<style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
- <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
- <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
<item name="background">@null</item>
<item name="backgroundStacked">@null</item>
<item name="backgroundSplit">@null</item>
+ <item name="displayOptions">useLogo|showHome|showTitle</item>
<item name="divider">?attr/dividerVertical</item>
+ <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
<item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
<item name="progressBarPadding">32dip</item>
<item name="itemPadding">8dip</item>
+ <item name="homeLayout">@layout/action_bar_home_quantum</item>
+ <item name="gravity">center_vertical</item>
</style>
<style name="Widget.Quantum.ActionBar.Solid">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7a11ce8..ac708b8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1092,6 +1092,7 @@
<java-symbol type="drawable" name="unlock_ring" />
<java-symbol type="drawable" name="unlock_wave" />
<java-symbol type="drawable" name="notification_bg" />
+ <java-symbol type="drawable" name="notification_bg_dim" />
<java-symbol type="drawable" name="notification_bg_low" />
<java-symbol type="drawable" name="notification_template_icon_bg" />
<java-symbol type="drawable" name="notification_template_icon_low_bg" />
@@ -1641,6 +1642,8 @@
<java-symbol type="layout" name="notification_template_quantum_inbox" />
<java-symbol type="color" name="notification_action_legacy_color_filter" />
<java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
+ <java-symbol type="drawable" name="notification_quantum_bg_dim" />
+ <java-symbol type="drawable" name="notification_quantum_bg" />
<!-- From SystemUI -->
<java-symbol type="anim" name="push_down_in" />
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index 9e235d6..a28496e 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -123,7 +123,7 @@
<item name="listSeparatorTextViewStyle">@style/Widget.Quantum.TextView.ListSeparator</item>
<item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
- <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+ <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
<item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_dark</item>
@@ -202,9 +202,9 @@
<item name="scrollbarTrackVertical">@null</item>
<!-- Text selection handle attributes -->
- <item name="textSelectHandleLeft">@drawable/text_select_handle_left</item>
- <item name="textSelectHandleRight">@drawable/text_select_handle_right</item>
- <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleLeft">@drawable/text_select_handle_left_quantum</item>
+ <item name="textSelectHandleRight">@drawable/text_select_handle_right_quantum</item>
+ <item name="textSelectHandle">@drawable/text_select_handle_middle_quantum</item>
<item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
<item name="textSuggestionsWindowStyle">@style/Widget.Quantum.TextSuggestionsPopupWindow</item>
<item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
@@ -300,10 +300,10 @@
<item name="actionModeStyle">@style/Widget.Quantum.ActionMode</item>
<item name="actionModeCloseButtonStyle">@style/Widget.Quantum.ActionButton.CloseMode</item>
<item name="actionBarStyle">@style/Widget.Quantum.ActionBar.Solid</item>
- <item name="actionBarSize">@dimen/action_bar_default_height</item>
+ <item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
<item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
<item name="actionBarWidgetTheme">@null</item>
- <item name="actionBarTheme">@null</item>
+ <item name="actionBarTheme">@style/ThemeOverlay.Quantum.ActionBarWidget</item>
<item name="actionBarItemBackground">@drawable/item_background_quantum</item>
<item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -321,7 +321,14 @@
<item name="segmentedButtonStyle">@style/Widget.Quantum.SegmentedButton</item>
<!-- SearchView attributes -->
- <item name="searchDropdownBackground">@drawable/search_dropdown_dark</item>
+ <item name="searchDropdownBackground">?attr/colorBackground</item>
+ <item name="searchViewTextField">@drawable/textfield_search_quantum</item>
+ <item name="searchViewTextFieldRight">@drawable/textfield_search_quantum</item>
+ <item name="searchViewCloseIcon">@android:drawable/ic_clear_quantum</item>
+ <item name="searchViewSearchIcon">@android:drawable/ic_search_api_quantum</item>
+ <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_quantum</item>
+ <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_quantum</item>
+ <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_quantum</item>
<item name="searchDialogTheme">@style/Theme.Quantum.SearchBar</item>
@@ -459,7 +466,7 @@
<item name="listSeparatorTextViewStyle">@style/Widget.Quantum.Light.TextView.ListSeparator</item>
<item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
- <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+ <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
<item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_light</item>
@@ -537,9 +544,9 @@
<item name="scrollbarTrackVertical">@null</item>
<!-- Text selection handle attributes -->
- <item name="textSelectHandleLeft">@drawable/text_select_handle_left</item>
- <item name="textSelectHandleRight">@drawable/text_select_handle_right</item>
- <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleLeft">@drawable/text_select_handle_left_quantum</item>
+ <item name="textSelectHandleRight">@drawable/text_select_handle_right_quantum</item>
+ <item name="textSelectHandle">@drawable/text_select_handle_middle_quantum</item>
<item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
<item name="textSuggestionsWindowStyle">@style/Widget.Quantum.Light.TextSuggestionsPopupWindow</item>
<item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
@@ -638,10 +645,10 @@
<item name="actionModeStyle">@style/Widget.Quantum.Light.ActionMode</item>
<item name="actionModeCloseButtonStyle">@style/Widget.Quantum.Light.ActionButton.CloseMode</item>
<item name="actionBarStyle">@style/Widget.Quantum.Light.ActionBar.Solid</item>
- <item name="actionBarSize">@dimen/action_bar_default_height</item>
+ <item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
<item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
<item name="actionBarWidgetTheme">@null</item>
- <item name="actionBarTheme">@null</item>
+ <item name="actionBarTheme">@style/ThemeOverlay.Quantum.Light.ActionBarWidget</item>
<item name="actionBarItemBackground">@drawable/item_background_quantum</item>
<item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -659,7 +666,14 @@
<item name="segmentedButtonStyle">@style/Widget.Quantum.Light.SegmentedButton</item>
<!-- SearchView attributes -->
- <item name="searchDropdownBackground">@drawable/search_dropdown_light</item>
+ <item name="searchDropdownBackground">?attr/colorBackground</item>
+ <item name="searchViewTextField">@drawable/textfield_search_quantum</item>
+ <item name="searchViewTextFieldRight">@drawable/textfield_search_quantum</item>
+ <item name="searchViewCloseIcon">@android:drawable/ic_clear_quantum</item>
+ <item name="searchViewSearchIcon">@android:drawable/ic_search_api_quantum</item>
+ <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_quantum</item>
+ <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_quantum</item>
+ <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_quantum</item>
<item name="searchDialogTheme">@style/Theme.Quantum.Light.SearchBar</item>
@@ -708,12 +722,29 @@
<item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
</style>
+ <style name="ThemeOverlay" />
+ <style name="ThemeOverlay.Quantum" />
+ <style name="ThemeOverlay.Quantum.Light" />
+
+ <!-- Variant of the quantum theme that replaces the activated control color
+ (which by default is identical to the action bar background color) with
+ the normal control color . -->
+ <style name="ThemeOverlay.Quantum.ActionBarWidget">
+ <item name="colorControlActivated">?attr/colorControlNormal</item>
+ </style>
+
+ <!-- Variant of the quantum (light) theme that replaces the activated control
+ color (which by default is identical to the action bar background color)
+ with the normal control color . -->
+ <style name="ThemeOverlay.Quantum.Light.ActionBarWidget">
+ <item name="colorControlActivated">?attr/colorControlNormal</item>
+ </style>
+
<!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
with an inverse color profile. The dark action bar sharply stands out against
the light content. -->
<style name="Theme.Quantum.Light.DarkActionBar">
- <item name="actionBarWidgetTheme">@null</item>
- <item name="actionBarTheme">@style/Theme.Quantum</item>
+ <!-- TODO -->
</style>
<!-- Variant of the quantum (dark) theme with no action bar. -->
diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java
new file mode 100644
index 0000000..9005188
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+
+public class NetworkKeyTest extends TestCase {
+ public void testValidWifiKey_utf8() {
+ new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23:03");
+ new WifiKey("\"\"", "AB:CD:01:EF:23:03");
+ }
+
+ public void testValidWifiKey_hex() {
+ new WifiKey("0x1234abcd", "AB:CD:01:EF:23:03");
+ }
+
+ public void testInvalidWifiKey_empty() {
+ try {
+ new WifiKey("", "AB:CD:01:EF:23:03");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected - empty SSID
+ }
+ }
+
+ public void testInvalidWifiKey_unquotedUtf8() {
+ try {
+ new WifiKey("unquotedSsid", "AB:CD:01:EF:23:03");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected - empty SSID
+ }
+ }
+
+ public void testInvalidWifiKey_invalidHex() {
+ try {
+ new WifiKey("0x\"nothex\"", "AB:CD:01:EF:23:03");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected - empty SSID
+ }
+ }
+
+ public void testInvalidWifiKey_shortBssid() {
+ try {
+ new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected - BSSID too short
+ }
+ }
+
+ public void testInvalidWifiKey_longBssid() {
+ try {
+ new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23:03:11");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected - BSSID too long
+ }
+ }
+
+ public void testParceling() {
+ WifiKey wifiKey = new WifiKey("\"ssid\"", "00:00:00:00:00:00");
+ NetworkKey networkKey = new NetworkKey(wifiKey);
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ parcel.writeParcelable(networkKey, 0);
+ parcel.setDataPosition(0);
+ networkKey = parcel.readParcelable(getClass().getClassLoader());
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+
+ assertEquals(NetworkKey.TYPE_WIFI, networkKey.type);
+ assertEquals("\"ssid\"", networkKey.wifiKey.ssid);
+ assertEquals("00:00:00:00:00:00", networkKey.wifiKey.bssid);
+ }
+}
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
new file mode 100644
index 0000000..7ab69ad
--- /dev/null
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.net;
+
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class ScoredNetworkTest extends TestCase {
+ private static final RssiCurve CURVE =
+ new RssiCurve(-110, 10, new byte[] {0, 1, 2, 3, 4, 5, 6, 7});
+
+ public void testInvalidCurve_nullBuckets() {
+ try {
+ new RssiCurve(-110, 10, null);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testInvalidCurve_emptyBuckets() {
+ try {
+ new RssiCurve(-110, 10, new byte[] {});
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testParceling() {
+ NetworkKey key = new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00"));
+ ScoredNetwork network = new ScoredNetwork(key, CURVE);
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ parcel.writeParcelable(network, 0);
+ parcel.setDataPosition(0);
+ network = parcel.readParcelable(getClass().getClassLoader());
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ assertEquals(CURVE.start, network.rssiCurve.start);
+ assertEquals(CURVE.bucketWidth, network.rssiCurve.bucketWidth);
+ assertTrue(Arrays.equals(CURVE.rssiBuckets, network.rssiCurve.rssiBuckets));
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
index efd06bf..18411b0 100644
--- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
@@ -438,17 +438,6 @@
assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
panelColor.getColor(), Color.RED);
}
-
- @SmallTest
- public void testModestyPanelHasDefault() {
- inflate(R.layout.size_adaptive);
- View panel = mSizeAdaptiveLayout.getModestyPanel();
- assertNull("SizeAdaptiveLayout should have no background for this test",
- mSizeAdaptiveLayout.getBackground());
- assertTrue("ModestyPanel should have a ColorDrawable background",
- panel.getBackground() instanceof ColorDrawable);
- }
-
@SmallTest
public void testOpenSmallEvenWhenLargeIsActuallySmall() {
inflate(R.layout.size_adaptive_lies);
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index d2177ca..03addfd 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -8,7 +8,7 @@
<h2>In this document</h2>
<ol class="toc">
- <li><a href="#usage">How to Use CCS</a>
+ <li><a href="#connecting">Establishing a Connection</a>
<ol class="toc">
<li><a href="#auth">Authentication</a></li>
</ol>
@@ -46,19 +46,20 @@
<p class="note"><strong>Note:</strong> To try out this feature, sign up using
<a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
-<p>The GCM Cloud Connection Server (CCS) is a connection server based on XMPP.
-CCS allows 3rd-party app servers (which you're
-responsible for implementing) to communicate
-with Android devices by establishing a persistent TCP connection with Google
-servers using the XMPP protocol. This communication is asynchronous and bidirectional.</p>
+<p>The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a
+persistent, asynchronous, bidirectional connection to Google servers. The
+connection can be used to send and receive messages between your server and
+your users' GCM-connected devices.</p>
+
<p>You can continue to use the HTTP request mechanism to send messages to GCM
servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
+
<ul>
<li>The asynchronous nature of XMPP allows you to send more messages with fewer
resources.</li>
- <li>Communication is bidirectional—not only can the server send messages
-to the device, but the device can send messages back to the server.</li>
-<li>You can send messages back using the same connection used for receiving,
+ <li>Communication is bidirectional—not only can your server send messages
+to the device, but the device can send messages back to your server.</li>
+ <li>The device can send messages back using the same connection used for receiving,
thereby improving battery life.</li>
</ul>
@@ -73,22 +74,34 @@
<a href="server.html#params">Implementing GCM Server</a> for a list of all the message
parameters and which connection server(s) supports them.</p>
+<h2 id="connecting">Establishing a Connection</h2>
-<h2 id="usage">How to Use CCS</h2>
+<p>CCS just uses XMPP as an authenticated transport layer, so you can use most
+XMPP libraries to manage the connection. For an example, see <a href="#smack">
+Java sample using the Smack library</a>.</p>
-<p>GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on
-{@code http://gcm.googleapis.com} port 5235.</p>
+<p>The CCS XMPP endpoint runs at {@code gcm.googleapis.com:5235}. When testing
+functionality (with non-production users), you should instead connect to
+{@code gcm-staging.googleapis.com:5236} (note the different port). Testing on
+staging (a smaller environment where the latest CCS builds run) is beneficial
+both for isolating real users from test code, as well as for early detection of
+unexpected behavior changes.</p>
-<p>CCS requires a Transport Layer Security (TLS) connection. That means the XMPP
-client must initiate a TLS connection.
-For example in Java, you would call {@code setSocketFactory(SSLSocketFactory)}.</p>
+<p>The connection has two important requirements:</p>
-<p>CCS requires a SASL PLAIN authentication mechanism using
-{@code <your_GCM_Sender_Id>@gcm.googleapis.com} (GCM sender ID) and the
-API key as the password, where the sender ID and API key are the same as described
-in <a href="gs.html">Getting Started</a>.</p>
+<ul>
+ <li>You must initiate a Transport Layer Security (TLS) connection. Note that
+ CCS doesn't currently support the <a href="http://xmpp.org/rfcs/rfc3920.html"
+ class="external-link" target="_android">STARTTLS extension</a>.</li>
+ <li>CCS requires a SASL PLAIN authentication mechanism using
+ {@code <your_GCM_Sender_Id>@gcm.googleapis.com} (GCM sender ID)
+ and the API key as the password, where the sender ID and API key are the same
+ as described in <a href="gs.html">Getting Started</a>.</li>
+</ul>
-<p> You can use most XMPP libraries to interact with CCS.</p>
+<p>If at any point the connection fails, you should immediately reconnect.
+There is no need to back off after a disconnect that happens after
+authentication.</p>
<h3 id="auth">Authentication</h3>
@@ -100,11 +113,11 @@
</pre>
<h4>Server</h4>
<pre><str:features xmlns:str="http://etherx.jabber.org/streams">
- <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
- <mechanism>X-OAUTH2</mechanism>
- <mechanism>X-GOOGLE-TOKEN</mechanism>
- <mechanism>PLAIN</mechanism>
- </mechanisms>
+ <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
+ <mechanism>X-OAUTH2</mechanism>
+ <mechanism>X-GOOGLE-TOKEN</mechanism>
+ <mechanism>PLAIN</mechanism>
+ </mechanisms>
</str:features>
</pre>
@@ -118,16 +131,18 @@
<pre><success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/></pre>
<h2 id="format">Message Format</h2>
-<p>CCS uses normal XMPP <code><message></code> stanzas. The body of the message must be:
-</p>
+<p>Once the XMPP connection is established, CCS and your server use normal XMPP
+<code><message></code> stanzas to send JSON-encoded messages back and
+forth. The body of the <code><message></code> must be:</p>
<pre>
<gcm xmlns:google:mobile:data>
<em>JSON payload</em>
</gcm>
</pre>
-<p>The JSON payload for server-to-device is similar to what the GCM http endpoint
-uses, with these exceptions:</p>
+<p>The JSON payload for regular GCM messages is similar to
+<a href="http.html#request">what the GCM http endpoint uses</a>, with these
+exceptions:</p>
<ul>
<li>There is no support for multiple recipients.</li>
<li>{@code to} is used instead of {@code registration_ids}.</li>
@@ -136,14 +151,13 @@
{@code message_id} to identify a message sent from 3rd-party app servers to CCS.
Therefore, it's important that this {@code message_id} not only be unique, but
always present.</li>
-
-<li>For ACK/NACK messages that are special control messages, you also need to
-include a {@code message_type} field in the JSON message. The value can be either
-'ack' or 'nack'. For example:
-
-<pre>message_type = ('ack');</pre>
- </li>
</ul>
+
+<p>In addition to regular GCM messages, control messages are sent, indicated by
+the {@code message_type} field in the JSON object. The value can be either
+'ack' or 'nack', or 'control' (see formats below). Any GCM message with an
+unknown {@code message_type} can be ignored by your server.</p>
+
<p>For each device message your app server receives from CCS, it needs to send
an ACK message.
It never needs to send a NACK message. If you don't send an ACK for a message,
@@ -251,7 +265,9 @@
</message></pre>
-<p>The following table lists some of the more common NACK error codes.</p>
+<p>The following table lists NACK error codes. Unless otherwise
+indicated, a NACKed message should not be retried. Unexpected NACK error codes
+should be treated the same as {@code INTERNAL_SERVER_ERROR}.</p>
<p class="table-caption" id="table1">
<strong>Table 1.</strong> NACK error codes.</p>
@@ -262,8 +278,17 @@
<th>Description</th>
</tr>
<tr>
+<td>{@code BAD_ACK}</td>
+<td>The ACK message is improperly formed.</td>
+</tr>
+<tr>
<td>{@code BAD_REGISTRATION}</td>
-<td>The device has a registration ID, but it's invalid.</td>
+<td>The device has a registration ID, but it's invalid or expired.</td>
+</tr>
+<tr>
+<td>{@code CONNECTION_DRAINING}</td>
+<td>The message couldn't be processed because the connection is draining. The
+message should be immediately retried over another connection.</td>
</tr>
<tr>
<td>{@code DEVICE_UNREGISTERED}</td>
@@ -274,25 +299,20 @@
<td>The server encountered an error while trying to process the request.</td>
</tr>
<tr>
+<td>{@code INVALID_JSON}</td>
+<td>The JSON message payload was not valid.</td>
+</tr>
+<tr>
+<td>{@code QUOTA_EXCEEDED}</td>
+<td>The rate of messages to a particular registration ID (in other words, to a
+sender/device pair) is too high. If you want to retry the message, try using a slower
+rate.</td>
+</tr>
+<tr>
<td>{@code SERVICE_UNAVAILABLE}</td>
-<td>The CCS connection server is temporarily unavailable, try again later
-(using exponential backoff, etc.).</td>
-</tr>
-<tr>
-<td>{@code BAD_ACK}</td>
-<td>The ACK message is improperly formed.</td>
-</tr>
-<tr>
-<td>{@code AUTHENTICATION_FAILED}</td>
-<td>This is a 401 error indicating that there was an error authenticating the sender account.</td>
-</tr>
-<tr>
-<td>{@code INVALID_TTL}</td>
-<td>There was an error in the supplied "time to live" value.</td>
-</tr>
-<tr>
-<td>{@code JSON_TYPE_ERROR}</td>
-<td>There was an error in the supplied JSON data type.</td>
+<td>CCS is not currently able to process the message. The
+message should be retried over the same connection using exponential backoff
+with an initial delay of 1 second.</td>
</tr>
</table>
@@ -319,6 +339,28 @@
</message>
</pre>
+<h4 id="control">Control messages</h4>
+
+<p>Periodically, CCS needs to close down a connection to perform load balancing. Before it
+closes the connection, CCS sends a {@code CONNECTION_DRAINING} message to indicate that the connection is being drained
+and will be closed soon. "Draining" refers to shutting off the flow of messages coming into a
+connection, but allowing whatever is already in the pipeline to continue. When you receive
+a {@code CONNECTION_DRAINING} message, you should immediately begin sending messages to another CCS
+connection, opening a new connection if necessary. You should, however, keep the original
+connection open and continue receiving messages that may come over the connection (and
+ACKing them)—CCS will handle initiating a connection close when it is ready.</p>
+
+<p>The {@code CONNECTION_DRAINING} message looks like this:</p>
+<pre><message>
+ <data:gcm xmlns:data="google:mobile:data">
+ {
+ "message_type":"control"
+ "control_type":"CONNECTION_DRAINING"
+ }
+ </data:gcm>
+</message></pre>
+
+<p>{@code CONNECTION_DRAINING} is currently the only {@code control_type} supported.</p>
<h2 id="upstream">Upstream Messages</h2>
@@ -381,7 +423,7 @@
<p>Every message sent to CCS receives either an ACK or a NACK response. Messages
that haven't received one of these responses are considered pending. If the pending
-message count reaches 1000, the 3rd-party app server should stop sending new messages
+message count reaches 100, the 3rd-party app server should stop sending new messages
and wait for CCS to acknowledge some of the existing pending messages as illustrated in
figure 1:</p>
@@ -395,7 +437,7 @@
if there are too many unacknowledged messages. Therefore, the 3rd-party app server
should "ACK" upstream messages, received from the client application via CCS, as soon as possible
to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't
-apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party app server
+apply to these ACKs. Even if the pending message count reaches 100, the 3rd-party app server
should continue sending ACKs for messages received from CCS to avoid blocking delivery of new
upstream messages.</p>
@@ -795,7 +837,7 @@
PASSWORD = "API Key"
REGISTRATION_ID = "Registration Id of the target device"
-unacked_messages_quota = 1000
+unacked_messages_quota = 100
send_queue = []
# Return a random alphanumerical id
diff --git a/docs/html/google/play-services/maps.jd b/docs/html/google/play-services/maps.jd
index c24cc74..c541b08 100644
--- a/docs/html/google/play-services/maps.jd
+++ b/docs/html/google/play-services/maps.jd
@@ -1,4 +1,4 @@
-page.title=Google Maps Android API
+page.title=Google Maps Android API v2
page.tags=mapview,location
header.hide=1
@@ -12,14 +12,14 @@
</div>
<div class="col-6">
- <h1 itemprop="name" style="margin-bottom:0;">Google Maps Android API</h1>
+ <h1 itemprop="name" style="margin-bottom:0;">Google Maps Android API v2</h1>
<p itemprop="description">Allow your users explore the world with rich maps provided by
Google. Identify locations with <b>custom markers</b>, augment the map data
with <b>image overlays</b>, embed <b>one or more maps</b> as fragments,
and much more.</p>
<p>Explore the <a
href="{@docRoot}reference/com/google/android/gms/maps/package-summary.html"
->Google Maps Android API reference</a> or visit <a class="external-link"
+>Google Maps Android API v2 reference</a> or visit <a class="external-link"
href="https://developers.google.com/maps/documentation/android/">developers.google.com/maps</a>
for more information about adding maps to your app.</p>
</div>
@@ -31,7 +31,7 @@
<div class="col-6 normal-links">
<h3 style="clear:left">Key Developer Features</h3>
<h4>Add maps to your app</h4>
- <p>With version 2 of the Google Maps Android API, you can embed maps into an activity
+ <p>With Google Maps Android API v2, you can embed maps into an activity
as a fragment with a simple XML snippet. The new Maps offer exciting features such as 3D maps;
indoor, satellite, terrain, and hybrid maps;
vector-based tiles for efficient caching and drawing; animated transitions; and much more.
@@ -58,7 +58,7 @@
<div class="col-6 normal-links">
<h3 style="clear:left">Getting Started</h3>
<h4>1. Get the Google Play services SDK</h4>
- <p>The Google Maps Android APIs are part of the Google Play services platform.</p>
+ <p>Google Maps Android API v2 is part of the Google Play services platform.</p>
<p>To use Google Maps, <a href="{@docRoot}google/play-services/setup.html">set up
the Google Play services SDK</a>. Then see the <a class="external-link"
href="https://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api">
@@ -69,7 +69,7 @@
<p>Once you've installed the Google Play services package, the Google Maps sample is located in
<code><android-sdk>/extras/google-play-services/samples/maps</code> and shows you
- how to use the major components of the Google Maps Android APIs.
+ how to use the major components of Google Maps Android API v2.
</p>
<h4>3. Read the documentation</h4>
@@ -79,9 +79,9 @@
<p>For quick access while developing your Android apps, the
<a href="{@docRoot}reference/com/google/android/gms/maps/package-summary.html">Google Maps
- Android API reference</a> is available here on developer.android.com.</p>
+ Android API v2 reference</a> is available here on developer.android.com.</p>
- <p>Detailed documentation for the Google Maps Android APIs is available with the rest of the
+ <p>Detailed documentation for Google Maps Android API v2 is available with the rest of the
Google Maps developer documents at <a class="external-link"
href="https://developers.google.com/maps/documentation/android/">developers.google.com/maps</a>.
</p>
diff --git a/docs/html/google/play-services/setup.jd b/docs/html/google/play-services/setup.jd
index 3137890..5df2629 100644
--- a/docs/html/google/play-services/setup.jd
+++ b/docs/html/google/play-services/setup.jd
@@ -104,7 +104,7 @@
dependencies {
compile 'com.android.support:appcompat-v7:+'
- <strong>compile 'com.google.android.gms:play-services:4.0.30'</strong>
+ <strong>compile 'com.google.android.gms:play-services:4.3.23'</strong>
}
</pre>
<p>Be sure you update this version number each time Google Play services is updated.</p>
@@ -235,4 +235,4 @@
<p>To then begin a connection to Google Play services, read <a
-href="{@docRoot}google/auth/api-client.html">Accessing Google Play Services APIs</a>.</p>
\ No newline at end of file
+href="{@docRoot}google/auth/api-client.html">Accessing Google Play Services APIs</a>.</p>
diff --git a/docs/html/images/gcm/CCS-ack.png b/docs/html/images/gcm/CCS-ack.png
index bce2ab2..4633157 100644
--- a/docs/html/images/gcm/CCS-ack.png
+++ b/docs/html/images/gcm/CCS-ack.png
Binary files differ
diff --git a/docs/image_sources/gcm/CCS-ack.graffle b/docs/image_sources/gcm/CCS-ack.graffle
new file mode 100644
index 0000000..addd456
--- /dev/null
+++ b/docs/image_sources/gcm/CCS-ack.graffle
@@ -0,0 +1,1580 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGrafflePro</string>
+ <string>139.18.0.187838</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {576.00002479553223, 733}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>BaseZoom</key>
+ <integer>0</integer>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2013-08-08 01:54:22 +0000</string>
+ <key>Creator</key>
+ <string>Katie McCormick</string>
+ <key>DisplayScale</key>
+ <string>1 0/72 in = 1.0000 in</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Bounds</key>
+ <string>{{89, 329}, {169, 44}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>250</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 Now app server can send\
+message no. 101}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{102, 266}, {114, 44}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>249</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 App server waits\
+for ack 1}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{153, 154}, {98, 44}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>244</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 Average\
+response time}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>226</integer>
+ <key>Position</key>
+ <real>0.375</real>
+ </dict>
+ <key>ID</key>
+ <integer>242</integer>
+ <key>Points</key>
+ <array>
+ <string>{263.00000095367432, 314.5}</string>
+ <string>{261, 99}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.112257</string>
+ <key>g</key>
+ <string>0.107007</string>
+ <key>r</key>
+ <string>0.934433</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>227</integer>
+ <key>Position</key>
+ <real>0.34722220897674561</real>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>227</integer>
+ <key>Position</key>
+ <real>0.3541666567325592</real>
+ </dict>
+ <key>ID</key>
+ <integer>241</integer>
+ <key>Points</key>
+ <array>
+ <string>{261, 99}</string>
+ <string>{262.50000071525574, 314.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.112257</string>
+ <key>g</key>
+ <string>0.107007</string>
+ <key>r</key>
+ <string>0.934433</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>226</integer>
+ <key>Position</key>
+ <real>0.375</real>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>227</integer>
+ </dict>
+ <key>ID</key>
+ <integer>240</integer>
+ <key>Points</key>
+ <array>
+ <string>{257.5, 336.5}</string>
+ <string>{288, 314.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.112257</string>
+ <key>g</key>
+ <string>0.107007</string>
+ <key>r</key>
+ <string>0.934433</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>239</integer>
+ <key>Points</key>
+ <array>
+ <string>{231, 288.50000116229057}</string>
+ <string>{231, 251.25}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.112257</string>
+ <key>g</key>
+ <string>0.107007</string>
+ <key>r</key>
+ <string>0.934433</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>238</integer>
+ <key>Position</key>
+ <real>0.56800001859664917</real>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>238</integer>
+ <key>Points</key>
+ <array>
+ <string>{231, 253}</string>
+ <string>{231, 315.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.112257</string>
+ <key>g</key>
+ <string>0.107007</string>
+ <key>r</key>
+ <string>0.934433</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{476, 33}, {49, 32}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>18</real>
+ </dict>
+ <key>ID</key>
+ <integer>230</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs36 \cf0 CCS}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{243, 35}, {101, 32}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>18</real>
+ </dict>
+ <key>ID</key>
+ <integer>229</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs36 \cf0 App Server}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>228</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 252}</string>
+ <string>{216, 252}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>227</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 314.5}</string>
+ <string>{216, 314.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>226</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 99}</string>
+ <string>{216, 99}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{393.69128000000001, 348.37441999999999}, {57, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>223</integer>
+ <key>Rotation</key>
+ <real>23</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 101}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{290.12054000000001, 420.17102}, {60, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>14</real>
+ </dict>
+ <key>ID</key>
+ <integer>222</integer>
+ <key>Rotation</key>
+ <real>341</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 100}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>220</integer>
+ <key>Points</key>
+ <array>
+ <string>{504, 351}</string>
+ <string>{288, 463}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{430.51697000000001, 279.19488999999999}, {44, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>14</real>
+ </dict>
+ <key>ID</key>
+ <integer>219</integer>
+ <key>Rotation</key>
+ <real>341</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack.. }</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{390.63733000000002, 258.42700000000002}, {44, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>14</real>
+ </dict>
+ <key>ID</key>
+ <integer>218</integer>
+ <key>Rotation</key>
+ <real>341</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 2}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{290.74178999999998, 239.21059}, {57, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>217</integer>
+ <key>Rotation</key>
+ <real>23</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 100}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{342.63623000000001, 185.82861}, {38, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>216</integer>
+ <key>Rotation</key>
+ <real>18</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no...}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{361.60431, 234}, {44, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>14</real>
+ </dict>
+ <key>ID</key>
+ <integer>209</integer>
+ <key>Rotation</key>
+ <real>341</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 1}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{351.16005999999999, 153.43960999999999}, {42, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>172</integer>
+ <key>Rotation</key>
+ <real>18</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 2}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{363, 117}, {42, 27}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>171</integer>
+ <key>Rotation</key>
+ <real>18</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 1}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>169</integer>
+ <key>Points</key>
+ <array>
+ <string>{504, 200.62189000000001}</string>
+ <string>{288, 312.62189000000001}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>168</integer>
+ <key>Points</key>
+ <array>
+ <string>{504, 241.00763000000001}</string>
+ <string>{288, 353.00763000000001}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>167</integer>
+ <key>Points</key>
+ <array>
+ <string>{504, 279}</string>
+ <string>{288, 391}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>165</integer>
+ <key>Points</key>
+ <array>
+ <string>{289, 391}</string>
+ <string>{505, 492}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>164</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 353}</string>
+ <string>{504, 454}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>163</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 313}</string>
+ <string>{504, 414}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>162</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 180}</string>
+ <string>{504, 281}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>161</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 252}</string>
+ <string>{504, 353}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>160</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 139.5}</string>
+ <string>{504, 240.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>158</integer>
+ <key>Position</key>
+ <real>0.29398149251937866</real>
+ </dict>
+ <key>ID</key>
+ <integer>159</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 98.000000596046448}</string>
+ <string>{504, 199.00000476837158}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.934433</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0.122713</string>
+ </dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>157</integer>
+ <key>Position</key>
+ <real>0.060185186564922333</real>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>158</integer>
+ <key>Points</key>
+ <array>
+ <string>{504, 72}</string>
+ <string>{504, 504}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>157</integer>
+ <key>Points</key>
+ <array>
+ <string>{288, 72}</string>
+ <string>{288, 504}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict>
+ <key>ShowsGrid</key>
+ <string>YES</string>
+ </dict>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>1</integer>
+ <key>ImageCounter</key>
+ <integer>1</integer>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>Layer 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>circoMinDist</key>
+ <real>18</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>dot</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2014-01-22 22:42:38 +0000</string>
+ <key>Modifier</key>
+ <string>Katie McCormick</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>PageBreaks</key>
+ <string>YES</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSHorizonalPagination</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>size</string>
+ <string>{612.00002479553223, 792}</string>
+ </array>
+ <key>NSPrintReverseOrientation</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <false/>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>Canvas 1</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array>
+ <dict>
+ <key>name</key>
+ <string>Canvas 1</string>
+ </dict>
+ </array>
+ <key>Frame</key>
+ <string>{{170, 139}, {1218, 882}}</string>
+ <key>ListView</key>
+ <true/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <false/>
+ <key>ShowRuler</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>120</integer>
+ <key>VisibleRegion</key>
+ <string>{{40.5, 0}, {534.5, 364}}</string>
+ <key>Zoom</key>
+ <real>2</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>Canvas 1</string>
+ <real>2</real>
+ <real>1</real>
+ </array>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 493e276..8fe06b5 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -206,6 +206,11 @@
return mVectorState;
}
+ @Override
+ public void jumpToCurrentState() {
+ mVectorState.mBasicAnimator.end();
+ }
+
/**
* Starts the animation.
*/
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 8b23955..285c8c3 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -63,7 +63,7 @@
}
}
-bool DeferredLayerUpdater::apply(bool* hasFunctors) {
+bool DeferredLayerUpdater::apply(TreeInfo& info) {
bool success = true;
// These properties are applied the same to both layer types
mLayer->setColorFilter(mColorFilter);
@@ -74,11 +74,7 @@
success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
}
mLayer->setBlend(mBlend);
- TreeInfo info = {0};
mDisplayList->prepareTree(info);
- if (info.hasFunctors) {
- *hasFunctors = true;
- }
mLayer->updateDeferred(mDisplayList.get(),
mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
mDirtyRect.setEmpty();
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 2cc9229..cc62caa 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -77,7 +77,7 @@
ANDROID_API void setPaint(const SkPaint* paint);
- ANDROID_API bool apply(bool* hasFunctors);
+ ANDROID_API bool apply(TreeInfo& info);
ANDROID_API Layer* backingLayer() {
return mLayer;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 06f675e..f19da9d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -286,12 +286,6 @@
int getFlags() const { return mFlags; }
private:
- SaveOp() {}
- DisplayListOp* reinit(int flags) {
- mFlags = flags;
- return this;
- }
-
int mFlags;
};
@@ -318,12 +312,6 @@
virtual const char* name() { return "RestoreToCount"; }
private:
- RestoreToCountOp() {}
- DisplayListOp* reinit(int count) {
- mCount = count;
- return this;
- }
-
int mCount;
};
@@ -514,7 +502,6 @@
}
protected:
- ClipOp() {}
virtual bool isRect() { return false; }
SkRegion::Op mOp;
@@ -539,13 +526,6 @@
virtual bool isRect() { return true; }
private:
- ClipRectOp() {}
- DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
- mOp = op;
- mArea.set(left, top, right, bottom);
- return this;
- }
-
Rect mArea;
};
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c55ebd6..cf21834 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
mNeedsDisplayListDataSync = false;
// Do a push pass on the old tree to handle freeing DisplayListData
// that are no longer used
- TreeInfo oldTreeInfo = {0};
+ TreeInfo oldTreeInfo;
prepareSubTree(oldTreeInfo, mDisplayListData);
// TODO: The damage for the old tree should be accounted for
delete mDisplayListData;
@@ -120,8 +120,15 @@
void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
if (subtree) {
- if (!info.hasFunctors) {
- info.hasFunctors = subtree->functorCount;
+ TextureCache& cache = Caches::getInstance().textureCache;
+ info.hasFunctors |= subtree->functorCount;
+ // TODO: Fix ownedBitmapResources to not require disabling prepareTextures
+ // and thus falling out of async drawing path.
+ if (subtree->ownedBitmapResources.size()) {
+ info.prepareTextures = false;
+ }
+ for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
+ info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]);
}
for (size_t i = 0; i < subtree->children().size(); i++) {
RenderNode* childNode = subtree->children()[i]->mDisplayList;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 9e6ee3f..6688952 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -66,7 +66,13 @@
class DrawDisplayListOp;
struct TreeInfo {
+ TreeInfo()
+ : hasFunctors(false)
+ , prepareTextures(false)
+ {}
+
bool hasFunctors;
+ bool prepareTextures;
// TODO: Damage calculations? Flag to skip staging pushes for RT animations?
};
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 7923ce7..e783905 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -25,14 +25,14 @@
namespace uirenderer {
Texture::Texture(): id(0), generation(0), blend(false), width(0), height(0),
- cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+ cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL), isInUse(false),
mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
mFirstFilter(true), mFirstWrap(true), mCaches(Caches::getInstance()) {
}
Texture::Texture(Caches& caches): id(0), generation(0), blend(false), width(0), height(0),
- cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+ cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL), isInUse(false),
mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
mFirstFilter(true), mFirstWrap(true), mCaches(caches) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index d48ec59..d5601f8 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -94,6 +94,12 @@
*/
const UvMapper* uvMapper;
+ /**
+ * Whether or not the Texture is marked in use and thus not evictable for
+ * the current frame. This is reset at the start of a new frame.
+ */
+ bool isInUse;
+
private:
/**
* Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 01d72d1..34e2265 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -121,29 +121,49 @@
// Caching
///////////////////////////////////////////////////////////////////////////////
-Texture* TextureCache::get(const SkBitmap* bitmap) {
+void TextureCache::resetMarkInUse() {
+ LruCache<const SkBitmap*, Texture*>::Iterator iter(mCache);
+ while (iter.next()) {
+ iter.value()->isInUse = false;
+ }
+}
+
+bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
+ if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
+ ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
+ bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+ return false;
+ }
+ return true;
+}
+
+// Returns a prepared Texture* that either is already in the cache or can fit
+// in the cache (and is thus added to the cache)
+Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
Texture* texture = mCache.get(bitmap);
if (!texture) {
- if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
- ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
- bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+ if (!canMakeTextureFromBitmap(bitmap)) {
return NULL;
}
const uint32_t size = bitmap->rowBytes() * bitmap->height();
+ bool canCache = size < mMaxSize;
// Don't even try to cache a bitmap that's bigger than the cache
- if (size < mMaxSize) {
- while (mSize + size > mMaxSize) {
+ while (canCache && mSize + size > mMaxSize) {
+ Texture* oldest = mCache.peekOldestValue();
+ if (oldest && !oldest->isInUse) {
mCache.removeOldest();
+ } else {
+ canCache = false;
}
}
- texture = new Texture();
- texture->bitmapSize = size;
- generateTexture(bitmap, texture, false);
+ if (canCache) {
+ texture = new Texture();
+ texture->bitmapSize = size;
+ generateTexture(bitmap, texture, false);
- if (size < mMaxSize) {
mSize += size;
TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
bitmap, texture->id, size, mSize);
@@ -151,16 +171,42 @@
ALOGD("Texture created, size = %d", size);
}
mCache.put(bitmap, texture);
- } else {
- texture->cleanup = true;
}
- } else if (bitmap->getGenerationID() != texture->generation) {
+ } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
+ // Texture was in the cache but is dirty, re-upload
+ // TODO: Re-adjust the cache size if the bitmap's dimensions have changed
generateTexture(bitmap, texture, true);
}
return texture;
}
+bool TextureCache::prefetchAndMarkInUse(const SkBitmap* bitmap) {
+ Texture* texture = getCachedTexture(bitmap);
+ if (texture) {
+ texture->isInUse = true;
+ }
+ return texture;
+}
+
+Texture* TextureCache::get(const SkBitmap* bitmap) {
+ Texture* texture = getCachedTexture(bitmap);
+
+ if (!texture) {
+ if (!canMakeTextureFromBitmap(bitmap)) {
+ return NULL;
+ }
+
+ const uint32_t size = bitmap->rowBytes() * bitmap->height();
+ texture = new Texture();
+ texture->bitmapSize = size;
+ generateTexture(bitmap, texture, false);
+ texture->cleanup = true;
+ }
+
+ return texture;
+}
+
Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
Texture* texture = new Texture();
texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index e33c60d..48a10c2 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -62,6 +62,18 @@
void operator()(const SkBitmap*& bitmap, Texture*& texture);
/**
+ * Resets all Textures to not be marked as in use
+ */
+ void resetMarkInUse();
+
+ /**
+ * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
+ * acquired for the bitmap, false otherwise. If a Texture was acquired it is
+ * marked as in use.
+ */
+ bool prefetchAndMarkInUse(const SkBitmap* bitmap);
+
+ /**
* Returns the texture associated with the specified bitmap. If the texture
* cannot be found in the cache, a new texture is generated.
*/
@@ -116,6 +128,11 @@
void setFlushRate(float flushRate);
private:
+
+ bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
+
+ Texture* getCachedTexture(const SkBitmap* bitmap);
+
/**
* Generates the texture from a bitmap into the specified texture structure.
*
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 3638184..16baf77 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -318,10 +318,10 @@
}
CanvasContext::~CanvasContext() {
- destroyCanvas();
+ destroyCanvasAndSurface();
}
-void CanvasContext::destroyCanvas() {
+void CanvasContext::destroyCanvasAndSurface() {
if (mCanvas) {
delete mCanvas;
mCanvas = 0;
@@ -382,13 +382,18 @@
mCanvas->setViewport(width, height);
}
-void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
- bool* hasFunctors) {
- LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
+void CanvasContext::makeCurrent() {
mGlobalContext->makeCurrent(mEglSurface);
+}
+
+void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+ TreeInfo& info) {
+ LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
+ makeCurrent();
for (size_t i = 0; i < layerUpdaters->size(); i++) {
DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
- LOG_ALWAYS_FATAL_IF(!update->apply(hasFunctors), "Failed to update layer!");
+ bool success = update->apply(info);
+ LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
if (update->backingLayer()->deferredUpdateScheduled) {
mCanvas->pushLayerUpdate(update->backingLayer());
}
@@ -444,8 +449,8 @@
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
requireGlContext();
- bool hasFunctors;
- layer->apply(&hasFunctors);
+ TreeInfo info;
+ layer->apply(info);
return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index dcb5957..a3fe591 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -23,6 +23,7 @@
#include <utils/Functor.h>
#include <utils/Vector.h>
+#include "../RenderNode.h"
#include "RenderTask.h"
#define FUNCTOR_PROCESS_DELAY 4
@@ -31,8 +32,6 @@
namespace uirenderer {
class DeferredLayerUpdater;
-class RenderNode;
-class DisplayListData;
class OpenGLRenderer;
class Rect;
class Layer;
@@ -54,9 +53,10 @@
void updateSurface(EGLNativeWindowType window);
void pauseSurface(EGLNativeWindowType window);
void setup(int width, int height);
- void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, bool* hasFunctors);
+ void makeCurrent();
+ void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
void drawDisplayList(RenderNode* displayList, Rect* dirty);
- void destroyCanvas();
+ void destroyCanvasAndSurface();
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index cf6c8db..f542d43 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -85,7 +85,6 @@
void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
- // canUnblockUiThread is temporary until WebView has a solution for syncing frame state
bool canUnblockUiThread = syncFrameState();
// Grab a copy of everything we need
@@ -105,17 +104,20 @@
}
}
+static void prepareTreeInfo(TreeInfo& info) {
+ info.prepareTextures = true;
+}
+
bool DrawFrameTask::syncFrameState() {
ATRACE_CALL();
-
- bool hasFunctors = false;
- mContext->processLayerUpdates(&mLayers, &hasFunctors);
-
- TreeInfo info = {0};
+ mContext->makeCurrent();
+ Caches::getInstance().textureCache.resetMarkInUse();
+ TreeInfo info;
+ prepareTreeInfo(info);
+ mContext->processLayerUpdates(&mLayers, info);
mRenderNode->prepareTree(info);
- hasFunctors |= info.hasFunctors;
-
- return !hasFunctors;
+ // If prepareTextures is false, we ran out of texture cache space
+ return !info.hasFunctors && info.prepareTextures;
}
void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b233ae9..ce490f1 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -140,15 +140,18 @@
mDrawFrameTask.drawFrame(&mRenderThread);
}
-CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
- args->context->destroyCanvas();
+CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
+ args->context->destroyCanvasAndSurface();
return NULL;
}
-void RenderProxy::destroyCanvas() {
- SETUP_TASK(destroyCanvas);
+void RenderProxy::destroyCanvasAndSurface() {
+ SETUP_TASK(destroyCanvasAndSurface);
args->context = mContext;
- post(task);
+ // destroyCanvasAndSurface() needs a fence as when it returns the
+ // underlying BufferQueue is going to be released from under
+ // the render thread.
+ postAndWait(task);
}
CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 3eb8ed8..a112493 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -65,7 +65,7 @@
ANDROID_API void setup(int width, int height);
ANDROID_API void drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
- ANDROID_API void destroyCanvas();
+ ANDROID_API void destroyCanvasAndSurface();
ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 058012b..c0f6a95 100644
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -24,7 +24,6 @@
#include <VideoEditorJava.h>
#include <VideoEditorOsal.h>
#include <VideoEditorLogging.h>
-#include <marker.h>
#include <VideoEditorClasses.h>
#include <VideoEditorThumbnailMain.h>
#include <M4OSA_Debug.h>
@@ -438,7 +437,7 @@
M4VS, (M4OSA_Char*)"videoEdito JNI overlayFile");
if (pContext->mOverlayFileName != NULL) {
strncpy (pContext->mOverlayFileName,
- (const char*)pContext->pEditSettings->\
+ (const char*)pContext->pEditSettings->
Effects[overlayEffectIndex].xVSS.pFramingFilePath, overlayFileNameLen);
//Change the name to png file
extPos = strstr(pContext->mOverlayFileName, ".rgb");
@@ -1560,9 +1559,6 @@
int *pOverlayIndex = M4OSA_NULL;
M4OSA_Char* pTempChar = M4OSA_NULL;
- // Add a code marker (the condition must always be true).
- ADD_CODE_MARKER_FUN(NULL != pEnv)
-
// Validate the settings parameter.
videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
(NULL == settings),
@@ -2196,10 +2192,6 @@
M4OSA_Context mContext = M4OSA_NULL;
jint* m_dst32 = M4OSA_NULL;
-
- // Add a text marker (the condition must always be true).
- ADD_TEXT_MARKER_FUN(NULL != env)
-
const char *pString = env->GetStringUTFChars(path, NULL);
if (pString == M4OSA_NULL) {
if (env != NULL) {
@@ -2537,9 +2529,6 @@
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_init()");
- // Add a text marker (the condition must always be true).
- ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
// Get the context.
pContext = (ManualEditContext*)videoEditClasses_getContext(&initialized, pEnv, thiz);
@@ -2948,9 +2937,6 @@
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_loadSettings()");
- // Add a code marker (the condition must always be true).
- ADD_CODE_MARKER_FUN(NULL != pEnv)
-
// Get the context.
pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded,
pEnv, thiz);
@@ -3123,9 +3109,6 @@
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_release()");
- // Add a text marker (the condition must always be true).
- ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
// Get the context.
pContext = (ManualEditContext*)videoEditClasses_getContext(&released, pEnv, thiz);
@@ -3633,15 +3616,9 @@
VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "JNI_OnLoad()");
- // Add a text marker (the condition must always be true).
- ADD_TEXT_MARKER_FUN(NULL != pVm)
-
// Check the JNI version.
if (pVm->GetEnv(&pEnv, JNI_VERSION_1_4) == JNI_OK)
{
- // Add a code marker (the condition must always be true).
- ADD_CODE_MARKER_FUN(NULL != pEnv)
-
// Register the manual edit JNI methods.
if (videoEditor_registerManualEditMethods((JNIEnv*)pEnv) == 0)
{
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index 2f8e357..ae1a80e 100644
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -26,7 +26,6 @@
#include <VideoEditorOsal.h>
#include <VideoEditorLogging.h>
#include <VideoEditorOsal.h>
-#include <marker.h>
extern "C" {
#include <M4OSA_Clock.h>
@@ -107,9 +106,6 @@
ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
"videoEditProp_getProperties()");
- // Add a text marker (the condition must always be true).
- ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
// Initialize the classes.
videoEditPropClass_init(&initialized, (JNIEnv*)pEnv);
@@ -192,9 +188,6 @@
// dereferencing of pClipProperties).
if (gotten)
{
- // Add a code marker (the condition must always be true).
- ADD_CODE_MARKER_FUN(NULL != pClipProperties)
-
// Log the API call.
VIDEOEDIT_LOG_API(
ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
@@ -316,9 +309,6 @@
videoEditOsal_free(pFile);
pFile = M4OSA_NULL;
- // Add a text marker (the condition must always be true).
- ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
// Return the Properties object.
return(properties);
}
diff --git a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
index 12f562b..21e21b5 100644
--- a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
@@ -24,7 +24,7 @@
<string name="restore_confirm_text" msgid="7499866728030461776">"Z pripojeného počítača bolo vyžiadané úplné obnovenie všetkých údajov. Chcete túto akciu povoliť?\n\nAk ste toto obnovenie nevyžiadali vy, túto operáciu nepovoľujte. Táto akcia nahradí všetky údaje v zariadení."</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Obnoviť údaje"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Neobnoviť"</string>
- <string name="current_password_text" msgid="8268189555578298067">"Zadajte svoje aktuálne heslo záloh nižšie:"</string>
+ <string name="current_password_text" msgid="8268189555578298067">"Zadajte svoje aktuálne heslo pre zálohu nižšie:"</string>
<string name="device_encryption_restore_text" msgid="1570864916855208992">"Zadajte svoje heslo na šifrovanie zariadenia nižšie."</string>
<string name="device_encryption_backup_text" msgid="5866590762672844664">"Zadajte svoje heslo na šifrovanie zariadenia nižšie. Bude tiež použité na šifrovanie archívu zálohy."</string>
<string name="backup_enc_password_text" msgid="4981585714795233099">"Zadajte heslo, ktoré sa použije pri šifrovaní údajov úplnej zálohy. Ak pole ponecháte prázdne, použije sa vaše aktuálne heslo zálohy:"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index baca387..28323b6 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -38,7 +38,7 @@
<string name="save_error" msgid="6167009778003223664">"Impossibile salvare il documento"</string>
<string name="create_error" msgid="3735649141335444215">"Impossibile creare la cartella"</string>
<string name="query_error" msgid="1222448261663503501">"Impossibile chiedere documenti"</string>
- <string name="root_recent" msgid="4470053704320518133">"Recenti"</string>
+ <string name="root_recent" msgid="4470053704320518133">"Recente"</string>
<string name="root_available_bytes" msgid="8568452858617033281">"<xliff:g id="SIZE">%1$s</xliff:g> liberi"</string>
<string name="root_type_service" msgid="2178854894416775409">"Servizi di archiviazione"</string>
<string name="root_type_shortcut" msgid="3318760609471618093">"Scorciatoie"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 42cec9c..f4e5582 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -44,8 +44,8 @@
<string name="root_type_shortcut" msgid="3318760609471618093">"Skróty"</string>
<string name="root_type_device" msgid="7121342474653483538">"Urządzenia"</string>
<string name="root_type_apps" msgid="8838065367985945189">"Więcej aplikacji"</string>
- <string name="pref_advanced_devices" msgid="903257239609301276">"Pokaż urządzenia zaawansowane"</string>
- <string name="pref_file_size" msgid="2826879315743961459">"Pokaż rozmiar pliku"</string>
+ <string name="pref_advanced_devices" msgid="903257239609301276">"Wyświetl urządzenia zaawansowane"</string>
+ <string name="pref_file_size" msgid="2826879315743961459">"Wyświetl rozmiar pliku"</string>
<string name="pref_device_size" msgid="3542106883278997222">"Wyświetl rozmiar urządzenia"</string>
<string name="empty" msgid="7858882803708117596">"Brak elementów"</string>
<string name="toast_no_application" msgid="1339885974067891667">"Nie można otworzyć pliku"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 269583a..75ecbcf 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"文件"</string>
- <string name="title_open" msgid="4353228937663917801">"開啟工具"</string>
+ <string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
<string name="title_save" msgid="2433679664882857999">"儲存至"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"建立資料夾"</string>
<string name="menu_grid" msgid="6878021334497835259">"格狀檢視"</string>
@@ -38,7 +38,7 @@
<string name="save_error" msgid="6167009778003223664">"無法儲存文件"</string>
<string name="create_error" msgid="3735649141335444215">"無法建立資料夾"</string>
<string name="query_error" msgid="1222448261663503501">"無法查詢文件"</string>
- <string name="root_recent" msgid="4470053704320518133">"最近使用過的項目"</string>
+ <string name="root_recent" msgid="4470053704320518133">"最近存取過"</string>
<string name="root_available_bytes" msgid="8568452858617033281">"可用空間:<xliff:g id="SIZE">%1$s</xliff:g>"</string>
<string name="root_type_service" msgid="2178854894416775409">"儲存空間服務"</string>
<string name="root_type_shortcut" msgid="3318760609471618093">"捷徑"</string>
@@ -47,7 +47,7 @@
<string name="pref_advanced_devices" msgid="903257239609301276">"顯示進階裝置"</string>
<string name="pref_file_size" msgid="2826879315743961459">"顯示檔案大小"</string>
<string name="pref_device_size" msgid="3542106883278997222">"顯示裝置大小"</string>
- <string name="empty" msgid="7858882803708117596">"沒有項目"</string>
+ <string name="empty" msgid="7858882803708117596">"沒有任何項目"</string>
<string name="toast_no_application" msgid="1339885974067891667">"無法開啟檔案"</string>
<string name="toast_failed_delete" msgid="2180678019407244069">"無法刪除部分文件"</string>
<string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
diff --git a/packages/FusedLocation/res/values-fr-rCA/strings.xml b/packages/FusedLocation/res/values-fr-rCA/strings.xml
index c7d33af..0d2cccc 100644
--- a/packages/FusedLocation/res/values-fr-rCA/strings.xml
+++ b/packages/FusedLocation/res/values-fr-rCA/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="5379477904423203699">"Tables de fusion"</string>
+ <string name="app_label" msgid="5379477904423203699">"Fused Location"</string>
</resources>
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 5b08674..1be44f9 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -19,7 +19,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) \
$(call all-proto-files-under,src)
-LOCAL_PACKAGE_NAME := Keyguard
+LOCAL_MODULE := Keyguard
LOCAL_CERTIFICATE := platform
@@ -30,6 +30,8 @@
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-include $(BUILD_PACKAGE)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index b2d2ec5..352317d 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -46,8 +46,5 @@
android:persistent="true"
android:supportsRtl="true">
- <service android:name=".KeyguardService"
- android:exported="true" />
-
</application>
</manifest>
diff --git a/packages/Keyguard/res/layout-land/keyguard_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
index 9f1c1f0..1d596d3 100644
--- a/packages/Keyguard/res/layout-land/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
@@ -21,7 +21,7 @@
and the security view. -->
<com.android.keyguard.KeyguardHostView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
index ebd0a64..49b4212 100644
--- a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
@@ -21,7 +21,7 @@
and the security view. -->
<com.android.keyguard.KeyguardSimpleHostView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml b/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
index da31065..50c2709 100644
--- a/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
@@ -19,7 +19,7 @@
<!-- This is the selector widget that allows the user to select an action. -->
<com.android.keyguard.KeyguardWidgetCarousel
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingLeft="25dp"
android:paddingRight="25dp"
diff --git a/packages/Keyguard/res/layout-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
index 136b296..8223db4 100644
--- a/packages/Keyguard/res/layout-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
@@ -21,7 +21,7 @@
and the security view. -->
<com.android.keyguard.KeyguardHostView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
index cba7667..ed600b0 100644
--- a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
@@ -21,7 +21,7 @@
and the security view. -->
<com.android.keyguard.KeyguardSimpleHostView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml b/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
index d0a07ca..6d7d864 100644
--- a/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
@@ -19,7 +19,7 @@
<!-- This is the selector widget that allows the user to select an action. -->
<com.android.keyguard.KeyguardWidgetPager
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_widget_container"
android:paddingLeft="25dp"
diff --git a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
index 85f6b6d..ba2f3a6 100644
--- a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -21,7 +21,7 @@
and the security view. -->
<com.android.keyguard.KeyguardHostView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_account_view.xml b/packages/Keyguard/res/layout/keyguard_account_view.xml
index 766effa..bde2ec6 100644
--- a/packages/Keyguard/res/layout/keyguard_account_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_account_view.xml
@@ -18,7 +18,7 @@
-->
<com.android.keyguard.KeyguardAccountView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_account_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_bouncer.xml b/packages/Keyguard/res/layout/keyguard_bouncer.xml
new file mode 100644
index 0000000..dedf427
--- /dev/null
+++ b/packages/Keyguard/res/layout/keyguard_bouncer.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <View android:id="@+id/bouncer_background"
+ android:background="#aa000000"
+ android:clickable="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+ <include layout="@layout/keyguard_simple_host_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</FrameLayout>
+
diff --git a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
index 94c68a5..8c8ec7a 100644
--- a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
@@ -20,7 +20,7 @@
<!-- This is the screen that allows the user to unlock by showing their face. -->
<com.android.keyguard.KeyguardFaceUnlockView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_face_unlock_view"
android:orientation="vertical"
android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml b/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
index c1d5326..83036ab 100644
--- a/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
+++ b/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
@@ -17,7 +17,7 @@
*/
-->
<com.android.keyguard.KeyguardMultiUserSelectorView
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
androidprv:layout_childType="userSwitcher"
android:id="@+id/keyguard_user_selector"
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index d8012bf..ed3f0e0 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -18,7 +18,7 @@
-->
<com.android.keyguard.KeyguardPasswordView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_password_view"
android:orientation="vertical"
android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index 0c9380c..3d7820f 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -22,7 +22,7 @@
is the portrait layout. -->
<com.android.keyguard.KeyguardPatternView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_pattern_view"
android:orientation="vertical"
android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_pin_view.xml b/packages/Keyguard/res/layout/keyguard_pin_view.xml
index 00c6a21..a804c8c 100644
--- a/packages/Keyguard/res/layout/keyguard_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pin_view.xml
@@ -19,7 +19,7 @@
<com.android.keyguard.KeyguardPINView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_pin_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_presentation.xml b/packages/Keyguard/res/layout/keyguard_presentation.xml
index 7df0b70..ab676aa 100644
--- a/packages/Keyguard/res/layout/keyguard_presentation.xml
+++ b/packages/Keyguard/res/layout/keyguard_presentation.xml
@@ -20,7 +20,7 @@
<!-- This is a view that shows general status information in Keyguard. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/presentation"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout/keyguard_selector_view.xml b/packages/Keyguard/res/layout/keyguard_selector_view.xml
index 6cb5e67..d3064ed 100644
--- a/packages/Keyguard/res/layout/keyguard_selector_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_selector_view.xml
@@ -20,7 +20,7 @@
<!-- This is the selector widget that allows the user to select an action. -->
<com.android.keyguard.KeyguardSelectorView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_selector_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
index eccac19..e96220e 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
@@ -19,7 +19,7 @@
<!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
<com.android.keyguard.KeyguardSimPinView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_sim_pin_view"
android:orientation="vertical"
android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
index fe37203..bf15ba0 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
@@ -20,7 +20,7 @@
carrier-provided PUK code and entering a new SIM PIN for it. -->
<com.android.keyguard.KeyguardSimPukView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_sim_puk_view"
android:orientation="vertical"
android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_status_area.xml b/packages/Keyguard/res/layout/keyguard_status_area.xml
index 98ba512..2730517 100644
--- a/packages/Keyguard/res/layout/keyguard_status_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_area.xml
@@ -20,7 +20,7 @@
<!-- This is a view that shows general status information in Keyguard. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index a4d298a..3b3a069 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -18,43 +18,38 @@
-->
<!-- This is a view that shows general status information in Keyguard. -->
-<com.android.keyguard.KeyguardWidgetFrame
+<com.android.keyguard.KeyguardStatusView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_status_view"
+ android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
- android:gravity="center">
-
- <com.android.keyguard.KeyguardStatusView
- android:id="@+id/keyguard_status_view_face_palm"
- android:orientation="vertical"
+ android:gravity="center_horizontal|top"
+ android:layout_marginTop="32dp"
+ android:layout_marginBottom="32dp"
+ android:contentDescription="@string/keyguard_accessibility_status">
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal|top"
- android:contentDescription="@string/keyguard_accessibility_status">
- <LinearLayout
- android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|top"
+ android:orientation="vertical"
+ android:focusable="true">
+ <TextClock
+ android:id="@+id/clock_view"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
- android:orientation="vertical"
- android:focusable="true">
- <TextClock
- android:id="@+id/clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:textColor="@color/clock_white"
- android:singleLine="true"
- style="@style/widget_big_thin"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:baselineAligned="true"
- android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
+ android:textColor="@color/clock_white"
+ android:singleLine="true"
+ style="@style/widget_big_thin"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format"
+ android:baselineAligned="true"
+ android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
- <include layout="@layout/keyguard_status_area" />
- </LinearLayout>
- </com.android.keyguard.KeyguardStatusView>
-</com.android.keyguard.KeyguardWidgetFrame>
+ <include layout="@layout/keyguard_status_area" />
+ </LinearLayout>
+</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 89ac293..cdf8ca9 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -35,7 +35,7 @@
<string name="keyguard_low_battery" msgid="8143808018719173859">"Pripojte nabíjačku."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Telefón odomknete stlačením tlačidla Menu."</string>
<string name="keyguard_network_locked_message" msgid="9169717779058037168">"Sieť je zablokovaná"</string>
- <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Nie je vložená karta SIM"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Nie je vložená karta SIM."</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"V tablete nie je žiadna karta SIM."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"V telefóne nie je žiadna karta SIM."</string>
<string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"Vložte kartu SIM."</string>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index c775467..19eb4c5 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -75,7 +75,7 @@
<string name="keyguard_accessibility_transport_thumbs_down_description" msgid="8101433677192177861">"Bài hát được đánh dấu không thích"</string>
<string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"Trái tim"</string>
<string name="keyguard_accessibility_show_bouncer" msgid="5425837272418176176">"Mở khóa để tiếp tục"</string>
- <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình chạy bị hủy"</string>
+ <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình khởi chạy bị hủy"</string>
<string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"Thả <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> để xóa."</string>
<string name="keyguard_accessibility_delete_widget_end" msgid="508833506780909393">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> sẽ không bị xóa."</string>
<string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index 71e9924..c05f834 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -158,7 +158,7 @@
<dimen name="bottom_text_spacing_digital">-8dp</dimen>
<dimen name="label_font_size">14dp</dimen>
<dimen name="widget_label_font_size">14dp</dimen>
- <dimen name="widget_big_font_size">80dp</dimen>
+ <dimen name="widget_big_font_size">60dp</dimen>
<dimen name="big_font_size">120dp</dimen>
</resources>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index 80fcf75..4a034aa 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -56,8 +56,7 @@
<!-- Built-in clock widget stuff -->
<style name="widget_label">
<item name="android:textStyle">bold</item>
- <item name="android:textAllCaps">true</item>
- <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:fontFamily">sans-serif-light</item>
<item name="android:textSize">@dimen/widget_label_font_size</item>
</style>
<style name="big_thin">
diff --git a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
index 74e6f33..2bf74ea 100644
--- a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
+++ b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
@@ -38,7 +38,7 @@
public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
private static final String TAG = CameraWidgetFrame.class.getSimpleName();
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final int WIDGET_ANIMATION_DURATION = 250; // ms
private static final int WIDGET_WAIT_DURATION = 400; // ms
private static final int RECOVERY_DELAY = 1000; // ms
@@ -113,12 +113,14 @@
private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
private boolean mShowing;
- void onKeyguardVisibilityChanged(boolean showing) {
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
if (mShowing == showing)
return;
mShowing = showing;
CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
- };
+ }
};
private static final class FixedSizeFrameLayout extends FrameLayout {
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index fd56613..4ed37d4 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -48,10 +48,11 @@
updateEmergencyCallButton(simState, phoneState);
}
- void onPhoneStateChanged(int phoneState) {
+ @Override
+ public void onPhoneStateChanged(int phoneState) {
State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
updateEmergencyCallButton(simState, phoneState);
- };
+ }
};
private LockPatternUtils mLockPatternUtils;
private PowerManager mPowerManager;
diff --git a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
index de839c6..2f14003 100644
--- a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
+++ b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
@@ -37,8 +37,9 @@
public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "FULLockscreen";
+ private static final String FACE_LOCK_PACKAGE = "com.android.facelock";
private final Context mContext;
private final LockPatternUtils mLockPatternUtils;
@@ -128,7 +129,8 @@
if (!mBoundToService) {
Log.d(TAG, "Binding to Face Unlock service for user="
+ mLockPatternUtils.getCurrentUser());
- mContext.bindServiceAsUser(new Intent(IFaceLockInterface.class.getName()),
+ mContext.bindServiceAsUser(
+ new Intent(IFaceLockInterface.class.getName()).setPackage(FACE_LOCK_PACKAGE),
mConnection,
Context.BIND_AUTO_CREATE,
new UserHandle(mLockPatternUtils.getCurrentUser()));
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 3950159..4b386b6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -231,7 +231,7 @@
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (mCallback != null) {
- mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
+ mCallback.userActivity(KeyguardConstants.DIGIT_PRESS_WAKE_MILLIS);
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 0d5e477..25f3383 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -43,7 +43,7 @@
public abstract class KeyguardActivityLauncher {
private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
private static final Intent SECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
new file mode 100644
index 0000000..bfa95f38
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard;
+
+/**
+ * Defines constants for the Keyguard.
+ */
+public class KeyguardConstants {
+
+ /**
+ * Turns on debugging information for the whole Keyguard. This is very verbose and should only
+ * be used temporarily for debugging.
+ */
+ public static final boolean DEBUG = false;
+
+ /** Timeout used for key presses. */
+ public static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
index 6bcbd6c..55f965c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -30,18 +30,18 @@
public class KeyguardDisplayManager {
protected static final String TAG = "KeyguardDisplayManager";
- private static boolean DEBUG = KeyguardViewMediator.DEBUG;
+ private static boolean DEBUG = KeyguardConstants.DEBUG;
Presentation mPresentation;
private MediaRouter mMediaRouter;
private Context mContext;
private boolean mShowing;
- KeyguardDisplayManager(Context context) {
+ public KeyguardDisplayManager(Context context) {
mContext = context;
mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
}
- void show() {
+ public void show() {
if (!mShowing) {
if (DEBUG) Slog.v(TAG, "show");
mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
@@ -51,7 +51,7 @@
mShowing = true;
}
- void hide() {
+ public void hide() {
if (mShowing) {
if (DEBUG) Slog.v(TAG, "hide");
mMediaRouter.removeCallback(mMediaRouterCallback);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
index c2cd32f..900d16e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
@@ -36,7 +36,7 @@
public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
private static final String TAG = "FULKeyguardFaceUnlockView";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private KeyguardSecurityCallback mKeyguardSecurityCallback;
private LockPatternUtils mLockPatternUtils;
private BiometricSensorUnlock mBiometricUnlock;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 2e76f19..7cfd684 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -61,7 +61,7 @@
public class KeyguardHostView extends KeyguardViewBase {
private static final String TAG = "KeyguardHostView";
- public static boolean DEBUG = KeyguardViewMediator.DEBUG;
+ public static boolean DEBUG = KeyguardConstants.DEBUG;
public static boolean DEBUGXPORT = true; // debug music transport control
// Transport control states.
@@ -118,7 +118,7 @@
void userActivity();
}
- /*package*/ interface OnDismissAction {
+ public interface OnDismissAction {
/* returns true if the dismiss should be deferred */
boolean onDismiss();
}
@@ -241,7 +241,7 @@
}
}
@Override
- void onMusicClientIdChanged(
+ public void onMusicClientIdChanged(
int clientGeneration, boolean clearing, android.app.PendingIntent intent) {
// Set transport state to invisible until we know music is playing (below)
if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) {
@@ -449,7 +449,7 @@
}
@Override
- protected void setLockPatternUtils(LockPatternUtils utils) {
+ public void setLockPatternUtils(LockPatternUtils utils) {
super.setLockPatternUtils(utils);
getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
index aa2ae0e..3aec55c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
@@ -37,7 +37,7 @@
class KeyguardMultiUserAvatar extends FrameLayout {
private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName();
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private ImageView mUserImage;
private TextView mUserName;
@@ -123,7 +123,7 @@
mUserName = (TextView) findViewById(R.id.keyguard_user_name);
mFramed = (KeyguardCircleFramedDrawable)
- KeyguardViewMediator.getAvatarCache().get(user.id);
+ MultiUserAvatarCache.getInstance().get(user.id);
// If we can't find it or the params don't match, create the drawable again
if (mFramed == null
@@ -143,7 +143,7 @@
mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke,
mFrameShadowColor, mShadowRadius, mHighlightColor);
- KeyguardViewMediator.getAvatarCache().put(user.id, mFramed);
+ MultiUserAvatarCache.getInstance().put(user.id, mFramed);
}
mFramed.reset();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 14de6dd..b4308c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -44,7 +44,7 @@
public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView {
private static final String TAG = "SecurityPatternView";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
// how long before we clear the wrong pattern
private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 0f62100..8425c48 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -30,7 +30,7 @@
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
- private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "KeyguardSecurityView";
private KeyguardSecurityModel mSecurityModel;
private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 70a0e44..07239d1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -38,7 +38,7 @@
*/
public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
private static final String TAG = "KeyguardSecurityViewFlipper";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private Rect mTempRect = new Rect();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index 97aec68..03e7b07 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -36,7 +36,6 @@
import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
private static final String TAG = "SecuritySelectorView";
private static final String ASSIST_ICON_METADATA_NAME =
"com.android.systemui.action_assist_icon";
@@ -57,12 +56,10 @@
public void onTrigger(View v, int target) {
final int resId = mGlowPadView.getResourceIdForTarget(target);
- switch (resId) {
- case R.drawable.ic_lockscreen_unlock_phantom:
- case R.drawable.ic_lockscreen_unlock:
- mCallback.userActivity(0);
- mCallback.dismiss(false);
- break;
+ if (resId == R.drawable.ic_lockscreen_unlock_phantom
+ || resId == R.drawable.ic_lockscreen_unlock) {
+ mCallback.userActivity(0);
+ mCallback.dismiss(false);
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index ae7ac97..d6a4f52 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -41,7 +41,7 @@
public class KeyguardSimPinView extends KeyguardAbsKeyInputView
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private static final String LOG_TAG = "KeyguardSimPinView";
- private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
public static final String TAG = "KeyguardSimPinView";
private ProgressDialog mSimUnlockProgressDialog = null;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index ca4f811..04cbde1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -42,7 +42,7 @@
public class KeyguardSimPukView extends KeyguardAbsKeyInputView
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private static final String LOG_TAG = "KeyguardSimPukView";
- private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
public static final String TAG = "KeyguardSimPukView";
private ProgressDialog mSimUnlockProgressDialog = null;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
index cf983cb..5d5168c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
@@ -38,11 +38,6 @@
}
@Override
- public void verifyUnlock() {
- // TODO Auto-generated method stub
- }
-
- @Override
public void cleanUp() {
// TODO Auto-generated method stub
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 0bfee38..ae55c4a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -33,7 +33,7 @@
import java.util.Locale;
public class KeyguardStatusView extends GridLayout {
- private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "KeyguardStatusView";
private LockPatternUtils mLockPatternUtils;
@@ -50,22 +50,22 @@
}
@Override
- void onKeyguardVisibilityChanged(boolean showing) {
+ public void onKeyguardVisibilityChanged(boolean showing) {
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
refresh();
}
- };
+ }
@Override
public void onScreenTurnedOn() {
setEnableMarquee(true);
- };
+ }
@Override
public void onScreenTurnedOff(int why) {
setEnableMarquee(false);
- };
+ }
};
public KeyguardStatusView(Context context) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
index a7cd909..0d472ae 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
@@ -60,7 +60,7 @@
public class KeyguardTransportControlView extends FrameLayout {
private static final int RESET_TO_METADATA_DELAY = 5000;
- protected static final boolean DEBUG = false;
+ protected static final boolean DEBUG = KeyguardConstants.DEBUG;
protected static final String TAG = "TransportControlView";
private static final boolean ANIMATE_TRANSITIONS = true;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 88c78ab..73c2840 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -72,7 +72,7 @@
public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final String TAG = "KeyguardUpdateMonitor";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_SIM_STATES = DEBUG || false;
private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
private static final int LOW_BATTERY_THRESHOLD = 20;
@@ -679,7 +679,7 @@
* broadcast and hence not handle the event. This method is ultimately called by
* PhoneWindowManager in this case.
*/
- protected void dispatchBootCompleted() {
+ public void dispatchBootCompleted() {
mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 556711b..862931e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -20,7 +20,7 @@
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.os.SystemClock;
-import android.util.Log;
+import android.telephony.TelephonyManager;
import android.view.WindowManagerPolicy;
import com.android.internal.telephony.IccCardConstants;
@@ -28,7 +28,7 @@
/**
* Callback for general information relevant to lock screen.
*/
-class KeyguardUpdateMonitorCallback {
+public class KeyguardUpdateMonitorCallback {
private static final long VISIBILITY_CHANGED_COLLAPSE_MS = 1000;
private long mVisibilityChangedCalled;
@@ -40,12 +40,12 @@
*
* @param status current battery status
*/
- void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
+ public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
/**
* Called once per minute or when the time changes.
*/
- void onTimeChanged() { }
+ public void onTimeChanged() { }
/**
* Called when the carrier PLMN or SPN changes.
@@ -54,14 +54,14 @@
* be displayed.
* @param spn The service provider name. May be null if it shouldn't be displayed.
*/
- void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
+ public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
/**
* Called when the ringer mode changes.
* @param state the current ringer state, as defined in
* {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
*/
- void onRingerModeChanged(int state) { }
+ public void onRingerModeChanged(int state) { }
/**
* Called when the phone state changes. String will be one of:
@@ -69,15 +69,15 @@
* {@link TelephonyManager@EXTRA_STATE_RINGING}
* {@link TelephonyManager#EXTRA_STATE_OFFHOOK
*/
- void onPhoneStateChanged(int phoneState) { }
+ public void onPhoneStateChanged(int phoneState) { }
/**
* Called when the visibility of the keyguard changes.
* @param showing Indicates if the keyguard is now visible.
*/
- void onKeyguardVisibilityChanged(boolean showing) { }
+ public void onKeyguardVisibilityChanged(boolean showing) { }
- void onKeyguardVisibilityChangedRaw(boolean showing) {
+ public void onKeyguardVisibilityChangedRaw(boolean showing) {
final long now = SystemClock.elapsedRealtime();
if (showing == mShowing
&& (now - mVisibilityChangedCalled) < VISIBILITY_CHANGED_COLLAPSE_MS) return;
@@ -90,44 +90,44 @@
* Called when visibility of lockscreen clock changes, such as when
* obscured by a widget.
*/
- void onClockVisibilityChanged() { }
+ public void onClockVisibilityChanged() { }
/**
* Called when the device becomes provisioned
*/
- void onDeviceProvisioned() { }
+ public void onDeviceProvisioned() { }
/**
* Called when the device policy changes.
* See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
*/
- void onDevicePolicyManagerStateChanged() { }
+ public void onDevicePolicyManagerStateChanged() { }
/**
* Called when the user change begins.
*/
- void onUserSwitching(int userId) { }
+ public void onUserSwitching(int userId) { }
/**
* Called when the user change is complete.
*/
- void onUserSwitchComplete(int userId) { }
+ public void onUserSwitchComplete(int userId) { }
/**
* Called when the SIM state changes.
* @param simState
*/
- void onSimStateChanged(IccCardConstants.State simState) { }
+ public void onSimStateChanged(IccCardConstants.State simState) { }
/**
* Called when a user is removed.
*/
- void onUserRemoved(int userId) { }
+ public void onUserRemoved(int userId) { }
/**
* Called when the user's info changed.
*/
- void onUserInfoChanged(int userId) { }
+ public void onUserInfoChanged(int userId) { }
/**
* Called when boot completed.
@@ -135,12 +135,12 @@
* Note, this callback will only be received if boot complete occurs after registering with
* KeyguardUpdateMonitor.
*/
- void onBootCompleted() { }
+ public void onBootCompleted() { }
/**
* Called when audio client attaches or detaches from AudioManager.
*/
- void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { }
+ public void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { }
/**
* Called when the audio playback state changes.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index 78f4506..bc0f364 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -60,7 +60,7 @@
private AudioManager mAudioManager;
private TelephonyManager mTelephonyManager = null;
- protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+ protected ViewMediatorCallback mViewMediatorCallback;
protected LockPatternUtils mLockPatternUtils;
private OnDismissAction mDismissAction;
@@ -68,7 +68,7 @@
// they will be handled here for specific media types such as music, otherwise
// the audio service will bring up the volume dialog.
private static final boolean KEYGUARD_MANAGES_VOLUME = true;
- private static final boolean DEBUG = false;
+ public static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "KeyguardViewBase";
private KeyguardSecurityContainer mSecurityContainer;
@@ -107,7 +107,6 @@
mSecurityContainer.setSecurityCallback(this);
mSecurityContainer.showPrimarySecurityScreen(false);
// mSecurityContainer.updateSecurityViews(false /* not bouncing */);
- setBackButtonEnabled(false);
}
/**
@@ -120,15 +119,11 @@
/**
* Dismisses the keyguard by going to the next screen or making it gone.
+ *
+ * @return True if the keyguard is done.
*/
- public void dismiss() {
- dismiss(false);
- }
-
- private void setBackButtonEnabled(boolean enabled) {
- setSystemUiVisibility(enabled ?
- getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
- getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
+ public boolean dismiss() {
+ return dismiss(false);
}
protected void showBouncer(boolean show) {
@@ -141,8 +136,7 @@
public boolean handleBackKey() {
if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
- // go back to primary screen and re-disable back
- setBackButtonEnabled(false);
+ // go back to primary screen
mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
return true;
}
@@ -205,12 +199,6 @@
@Override
public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
- // Enable or disable the back button based on security mode
- if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
- // we're showing account as a backup, provide a way to get back to primary
- setBackButtonEnabled(true);
- }
-
if (mViewMediatorCallback != null) {
mViewMediatorCallback.setNeedsInput(needsInput);
}
@@ -231,7 +219,7 @@
/**
* Called when the screen turned off.
*/
- protected void onScreenTurnedOff() {
+ public void onScreenTurnedOff() {
if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
// Once the screen turns off, we no longer consider this to be first boot and we want the
@@ -245,7 +233,7 @@
/**
* Called when the screen turned on.
*/
- protected void onScreenTurnedOn() {
+ public void onScreenTurnedOn() {
if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
mSecurityContainer.showPrimarySecurityScreen(false);
mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
@@ -433,8 +421,7 @@
return false;
}
- public void setViewMediatorCallback(
- KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
+ public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
mViewMediatorCallback = viewMediatorCallback;
// Update ViewMediator with the current input method requirements
mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
@@ -484,7 +471,7 @@
mActivityLauncher.launchCamera(getHandler(), null);
}
- protected void setLockPatternUtils(LockPatternUtils utils) {
+ public void setLockPatternUtils(LockPatternUtils utils) {
mLockPatternUtils = utils;
mSecurityContainer.setLockPatternUtils(utils);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
deleted file mode 100644
index 5b35ba88..0000000
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-
-import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.analytics.KeyguardAnalytics;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-
-/**
- * Manages creating, showing, hiding and resetting the keyguard. Calls back
- * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke
- * the wake lock and report that the keyguard is done, which is in turn,
- * reported to this class by the current {@link KeyguardViewBase}.
- */
-public class KeyguardViewManager {
- private final static boolean DEBUG = KeyguardViewMediator.DEBUG;
- private static String TAG = "KeyguardViewManager";
- public final static String IS_SWITCHING_USER = "is_switching_user";
-
- // Delay dismissing keyguard to allow animations to complete.
- private static final int HIDE_KEYGUARD_DELAY = 500;
-
- // Timeout used for keypresses
- static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
- private static final boolean ENABLE_SIMPLE_KEYGUARD = false;
-
- private final Context mContext;
- private final ViewManager mViewManager;
- private final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
- private final KeyguardAnalytics.Callback mAnalyticsCallback;
-
- private WindowManager.LayoutParams mWindowLayoutParams;
- private boolean mNeedsInput = false;
-
- private ViewManagerHost mKeyguardHost;
- private KeyguardViewBase mKeyguardView;
-
- private boolean mScreenOn = false;
- private LockPatternUtils mLockPatternUtils;
-
- private KeyguardUpdateMonitorCallback mBackgroundChanger = new KeyguardUpdateMonitorCallback() {
- @Override
- public void onSetBackground(Bitmap bmp) {
- mKeyguardHost.setCustomBackground(bmp != null ?
- new BitmapDrawable(mContext.getResources(), bmp) : null);
- updateShowWallpaper(bmp == null);
- }
- };
-
- public interface ShowListener {
- void onShown(IBinder windowToken);
- };
-
- /**
- * @param context Used to create views.
- * @param viewManager Keyguard will be attached to this.
- * @param callback Used to notify of changes.
- * @param lockPatternUtils
- */
- public KeyguardViewManager(Context context, ViewManager viewManager,
- KeyguardViewMediator.ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, KeyguardAnalytics.Callback analyticsCallback) {
- mContext = context;
- mViewManager = viewManager;
- mViewMediatorCallback = callback;
- mLockPatternUtils = lockPatternUtils;
- mAnalyticsCallback = analyticsCallback;
- }
-
- /**
- * Show the keyguard. Will handle creating and attaching to the view manager
- * lazily.
- */
- public synchronized void show(Bundle options) {
- if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
- if (mAnalyticsCallback != null) {
- mAnalyticsCallback.onShow();
- }
-
- boolean enableScreenRotation = shouldEnableScreenRotation();
-
- maybeCreateKeyguardLocked(enableScreenRotation, false, options);
- maybeEnableScreenRotation(enableScreenRotation);
-
- // Disable common aspects of the system/status/navigation bars that are not appropriate or
- // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
- // activities. Other disabled bits are handled by the KeyguardViewMediator talking
- // directly to the status bar service.
- int visFlags = View.STATUS_BAR_DISABLE_HOME;
- if (shouldEnableTranslucentDecor()) {
- mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
- }
- if (DEBUG) Log.v(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
- mKeyguardHost.setSystemUiVisibility(visFlags);
-
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- mKeyguardHost.setVisibility(View.VISIBLE);
- mKeyguardView.show();
- mKeyguardView.requestFocus();
- }
-
- private boolean shouldEnableScreenRotation() {
- Resources res = mContext.getResources();
- return SystemProperties.getBoolean("lockscreen.rot_override",false)
- || res.getBoolean(R.bool.config_enableLockScreenRotation);
- }
-
- private boolean shouldEnableTranslucentDecor() {
- Resources res = mContext.getResources();
- return res.getBoolean(R.bool.config_enableLockScreenTranslucentDecor);
- }
-
- class ViewManagerHost extends FrameLayout {
- private static final int BACKGROUND_COLOR = 0x70000000;
-
- private Drawable mCustomBackground;
-
- // This is a faster way to draw the background on devices without hardware acceleration
- private final Drawable mBackgroundDrawable = new Drawable() {
- @Override
- public void draw(Canvas canvas) {
- if (mCustomBackground != null) {
- final Rect bounds = mCustomBackground.getBounds();
- final int vWidth = getWidth();
- final int vHeight = getHeight();
-
- final int restore = canvas.save();
- canvas.translate(-(bounds.width() - vWidth) / 2,
- -(bounds.height() - vHeight) / 2);
- mCustomBackground.draw(canvas);
- canvas.restoreToCount(restore);
- } else {
- canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
- }
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
- };
-
- public ViewManagerHost(Context context) {
- super(context);
- setBackground(mBackgroundDrawable);
- }
-
- public void setCustomBackground(Drawable d) {
- mCustomBackground = d;
- if (d != null) {
- d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER);
- }
- computeCustomBackgroundBounds();
- invalidate();
- }
-
- private void computeCustomBackgroundBounds() {
- if (mCustomBackground == null) return; // Nothing to do
- if (!isLaidOut()) return; // We'll do this later
-
- final int bgWidth = mCustomBackground.getIntrinsicWidth();
- final int bgHeight = mCustomBackground.getIntrinsicHeight();
- final int vWidth = getWidth();
- final int vHeight = getHeight();
-
- final float bgAspect = (float) bgWidth / bgHeight;
- final float vAspect = (float) vWidth / vHeight;
-
- if (bgAspect > vAspect) {
- mCustomBackground.setBounds(0, 0, (int) (vHeight * bgAspect), vHeight);
- } else {
- mCustomBackground.setBounds(0, 0, vWidth, (int) (vWidth / bgAspect));
- }
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- computeCustomBackgroundBounds();
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- // only propagate configuration messages if we're currently showing
- maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
- } else {
- if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
- }
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (mKeyguardView != null) {
- // Always process back and menu keys, regardless of focus
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- int keyCode = event.getKeyCode();
- if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
- return true;
- }
- }
- // Always process media keys, regardless of focus
- if (mKeyguardView.dispatchKeyEvent(event)) {
- return true;
- }
- }
- return super.dispatchKeyEvent(event);
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- boolean result = false;
- if (mAnalyticsCallback != null) {
- result = mAnalyticsCallback.onTouchEvent(ev, getWidth(), getHeight()) || result;
- }
- return super.dispatchTouchEvent(ev) || result;
- }
- }
-
- SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
- private int mCurrentLayout;
-
- private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
- Bundle options) {
- if (mKeyguardHost != null) {
- mKeyguardHost.saveHierarchyState(mStateContainer);
- }
-
- if (mKeyguardHost == null) {
- if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
-
- mKeyguardHost = new ViewManagerHost(mContext);
-
- int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
- if (!mNeedsInput) {
- flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
-
- final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
- final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- lp.windowAnimations = R.style.Animation_LockScreen;
- lp.screenOrientation = enableScreenRotation ?
- ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-
- if (ActivityManager.isHighEndGfx()) {
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- lp.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
- }
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
- lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
- lp.setTitle("Keyguard");
- mWindowLayoutParams = lp;
- mViewManager.addView(mKeyguardHost, lp);
-
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
- }
-
- if (force || mKeyguardView == null) {
- mKeyguardHost.setCustomBackground(null);
- mKeyguardHost.removeAllViews();
- int layout = (allowNotificationsOnSecureKeyguard() && ENABLE_SIMPLE_KEYGUARD)
- ? R.layout.keyguard_simple_host_view
- : R.layout.keyguard_host_view;
- if (mCurrentLayout != layout) {
- mStateContainer.clear(); // don't restore to the wrong view hierarchy
- mCurrentLayout = layout;
- }
- mKeyguardView = inflateKeyguardView(options, layout);
- mKeyguardView.requestFocus();
- }
- updateUserActivityTimeoutInWindowLayoutParams();
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-
- mKeyguardHost.restoreHierarchyState(mStateContainer);
- }
-
- private boolean allowNotificationsOnSecureKeyguard() {
- ContentResolver cr = mContext.getContentResolver();
- return Settings.Global.getInt(cr, Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) == 1;
- }
-
- private KeyguardViewBase inflateKeyguardView(Bundle options, int layoutId) {
- View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
- if (v != null) {
- mKeyguardHost.removeView(v);
- }
- final LayoutInflater inflater = LayoutInflater.from(mContext);
- View view = inflater.inflate(layoutId, mKeyguardHost, true);
- KeyguardViewBase keyguard = (KeyguardViewBase) view.findViewById(R.id.keyguard_host_view);
- keyguard.setLockPatternUtils(mLockPatternUtils);
- keyguard.setViewMediatorCallback(mViewMediatorCallback);
- keyguard.onUserSwitching(options != null && options.getBoolean(IS_SWITCHING_USER));
- keyguard.onCreateOptions(options);
- return keyguard;
- }
-
- public void updateUserActivityTimeout() {
- updateUserActivityTimeoutInWindowLayoutParams();
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- }
-
- private void updateUserActivityTimeoutInWindowLayoutParams() {
- // Use the user activity timeout requested by the keyguard view, if any.
- if (mKeyguardView != null) {
- long timeout = mKeyguardView.getUserActivityTimeout();
- if (timeout >= 0) {
- mWindowLayoutParams.userActivityTimeout = timeout;
- return;
- }
- }
-
- // Otherwise, use the default timeout.
- mWindowLayoutParams.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
- }
-
- private void maybeEnableScreenRotation(boolean enableScreenRotation) {
- // TODO: move this outside
- if (enableScreenRotation) {
- if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
- mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
- } else {
- if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
- mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
- }
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- }
-
- void updateShowWallpaper(boolean show) {
- if (show) {
- mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
- } else {
- mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
- }
- mWindowLayoutParams.format = show ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
-
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- }
-
- public void setNeedsInput(boolean needsInput) {
- mNeedsInput = needsInput;
- if (mWindowLayoutParams != null) {
- if (needsInput) {
- mWindowLayoutParams.flags &=
- ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- } else {
- mWindowLayoutParams.flags |=
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
-
- try {
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- } catch (java.lang.IllegalArgumentException e) {
- // TODO: Ensure this method isn't called on views that are changing...
- Log.w(TAG,"Can't update input method on " + mKeyguardHost + " window not attached");
- }
- }
- }
-
- /**
- * Reset the state of the view.
- */
- public synchronized void reset(Bundle options) {
- if (DEBUG) Log.d(TAG, "reset()");
- // User might have switched, check if we need to go back to keyguard
- // TODO: It's preferable to stay and show the correct lockscreen or unlock if none
- maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, options);
- }
-
- public synchronized void onScreenTurnedOff() {
- if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
- mScreenOn = false;
- if (mKeyguardView != null) {
- mKeyguardView.onScreenTurnedOff();
- }
- }
-
- public synchronized void onScreenTurnedOn(final IKeyguardShowCallback callback) {
- if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
- mScreenOn = true;
-
- // If keyguard is not showing, we need to inform PhoneWindowManager with a null
- // token so it doesn't wait for us to draw...
- final IBinder token = isShowing() ? mKeyguardHost.getWindowToken() : null;
-
- if (DEBUG && token == null) Slog.v(TAG, "send wm null token: "
- + (mKeyguardHost == null ? "host was null" : "not showing"));
-
- if (mKeyguardView != null) {
- mKeyguardView.onScreenTurnedOn();
-
- // Caller should wait for this window to be shown before turning
- // on the screen.
- if (callback != null) {
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- // Keyguard may be in the process of being shown, but not yet
- // updated with the window manager... give it a chance to do so.
- mKeyguardHost.post(new Runnable() {
- @Override
- public void run() {
- try {
- callback.onShown(token);
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception calling onShown():", e);
- }
- }
- });
- } else {
- try {
- callback.onShown(token);
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception calling onShown():", e);
- }
- }
- }
- } else if (callback != null) {
- try {
- callback.onShown(token);
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception calling onShown():", e);
- }
- }
- if (mAnalyticsCallback != null) {
- mAnalyticsCallback.onScreenOn();
- }
- }
-
- public synchronized void verifyUnlock() {
- if (DEBUG) Log.d(TAG, "verifyUnlock()");
- show(null);
- mKeyguardView.verifyUnlock();
- }
-
- /**
- * Hides the keyguard view
- */
- public synchronized void hide() {
- if (DEBUG) Log.d(TAG, "hide()");
-
- if (mAnalyticsCallback != null) {
- mAnalyticsCallback.onHide();
- }
-
- if (mKeyguardHost != null) {
- mKeyguardHost.setVisibility(View.GONE);
-
- // We really only want to preserve keyguard state for configuration changes. Hence
- // we should clear state of widgets (e.g. Music) when we hide keyguard so it can
- // start with a fresh state when we return.
- mStateContainer.clear();
-
- // Don't do this right away, so we can let the view continue to animate
- // as it goes away.
- if (mKeyguardView != null) {
- final KeyguardViewBase lastView = mKeyguardView;
- mKeyguardView = null;
- mKeyguardHost.postDelayed(new Runnable() {
- @Override
- public void run() {
- synchronized (KeyguardViewManager.this) {
- lastView.cleanUp();
- // Let go of any large bitmaps.
- mKeyguardHost.setCustomBackground(null);
- updateShowWallpaper(true);
- mKeyguardHost.removeView(lastView);
- mViewMediatorCallback.keyguardGone();
- }
- }
- }, HIDE_KEYGUARD_DELAY);
- }
- }
- }
-
- /**
- * Dismisses the keyguard by going to the next screen or making it gone.
- */
- public synchronized void dismiss() {
- if (mScreenOn) {
- mKeyguardView.dismiss();
- }
- }
-
- /**
- * @return Whether the keyguard is showing
- */
- public synchronized boolean isShowing() {
- return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
- }
-
- public void showAssistant() {
- if (mKeyguardView != null) {
- mKeyguardView.showAssistant();
- }
- }
-
- public void dispatch(MotionEvent event) {
- if (mKeyguardView != null) {
- mKeyguardView.onExternalMotionEvent(event);
- }
- }
-
- public void launchCamera() {
- if (mKeyguardView != null) {
- mKeyguardView.launchCamera();
- }
- }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java b/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
index 9930e72..7128211 100644
--- a/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
+++ b/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
@@ -22,12 +22,21 @@
public class MultiUserAvatarCache {
+ private static MultiUserAvatarCache sInstance;
+
private final HashMap<Integer, Drawable> mCache;
- public MultiUserAvatarCache() {
+ private MultiUserAvatarCache() {
mCache = new HashMap<Integer, Drawable>();
}
+ public static MultiUserAvatarCache getInstance() {
+ if (sInstance == null) {
+ sInstance = new MultiUserAvatarCache();
+ }
+ return sInstance;
+ }
+
public void clear(int userId) {
mCache.remove(userId);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/PagedView.java b/packages/Keyguard/src/com/android/keyguard/PagedView.java
index d233ee9..b42a085 100644
--- a/packages/Keyguard/src/com/android/keyguard/PagedView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PagedView.java
@@ -56,7 +56,7 @@
public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
private static final int WARP_SNAP_DURATION = 160;
private static final String TAG = "WidgetPagedView";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_WARP = false;
protected static final int INVALID_PAGE = -1;
private static final int WARP_PEEK_ANIMATION_DURATION = 150;
diff --git a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
index 3d515ce..ab9286b 100644
--- a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
+++ b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
@@ -45,7 +45,7 @@
*/
public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout {
private static final String TAG = "SlidingChallengeLayout";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
// The drag handle is measured in dp above & below the top edge of the
// challenge view; these parameters change based on whether the challenge
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
new file mode 100644
index 0000000..1f23785
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard;
+
+/**
+ * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
+ * various things.
+ */
+public interface ViewMediatorCallback {
+ /**
+ * Reports user activity and requests that the screen stay on.
+ */
+ void userActivity();
+
+ /**
+ * Reports user activity and requests that the screen stay on for at least
+ * the specified amount of time.
+ * @param millis The amount of time in millis. This value is currently ignored.
+ */
+ void userActivity(long millis);
+
+ /**
+ * Report that the keyguard is done.
+ * @param authenticated Whether the user securely got past the keyguard.
+ * the only reason for this to be false is if the keyguard was instructed
+ * to appear temporarily to verify the user is supposed to get past the
+ * keyguard, and the user fails to do so.
+ */
+ void keyguardDone(boolean authenticated);
+
+ /**
+ * Report that the keyguard is done drawing.
+ */
+ void keyguardDoneDrawing();
+
+ /**
+ * Tell ViewMediator that the current view needs IME input
+ * @param needsInput
+ */
+ void setNeedsInput(boolean needsInput);
+
+ /**
+ * Tell view mediator that the keyguard view's desired user activity timeout
+ * has changed and needs to be reapplied to the window.
+ */
+ void onUserActivityTimeoutChanged();
+
+ /**
+ * Report that the keyguard is dismissable, pending the next keyguardDone call.
+ */
+ void keyguardDonePending();
+
+ /**
+ * Report when keyguard is actually gone
+ */
+ void keyguardGone();
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
index 55750cc..20af2f1 100644
--- a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
@@ -80,7 +80,7 @@
public void onScreenOn();
public void onScreenOff();
public boolean onTouchEvent(MotionEvent ev, int width, int height);
- public void onSetHidden(boolean hidden);
+ public void onSetOccluded(boolean hidden);
}
public interface SessionTypeAdapter {
@@ -256,11 +256,11 @@
}
@Override
- public void onSetHidden(boolean hidden) {
+ public void onSetOccluded(boolean hidden) {
synchronized (KeyguardAnalytics.this) {
if (hidden != mHidden) {
if (DEBUG) {
- Log.d(TAG, "onSetHidden(" + hidden + ")");
+ Log.d(TAG, "onSetOccluded(" + hidden + ")");
}
mHidden = hidden;
if (hidden) {
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 1a871f8..74190b4 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -69,8 +69,8 @@
<item msgid="2762241247228983754">"Farve"</item>
</string-array>
<string-array name="orientation_labels">
- <item msgid="4061931020926489228">"Stående"</item>
- <item msgid="3199660090246166812">"Liggende"</item>
+ <item msgid="4061931020926489228">"Portræt"</item>
+ <item msgid="3199660090246166812">"Landskab"</item>
</string-array>
<string-array name="page_options_labels">
<item msgid="7421377442011699994">"Alle"</item>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index e299508..5d4fe94 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -69,7 +69,7 @@
<item msgid="2762241247228983754">"Barvno"</item>
</string-array>
<string-array name="orientation_labels">
- <item msgid="4061931020926489228">"Pokončno"</item>
+ <item msgid="4061931020926489228">"Navpično"</item>
<item msgid="3199660090246166812">"Ležeče"</item>
</string-array>
<string-array name="page_options_labels">
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index a84e9b3..55c8687 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -31,7 +31,7 @@
<string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha kitazamaji cha PDF kwa onyesho la kuchungulia"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Programu ya kuchapisha imeacha kufanya kazi"</string>
<string name="page_count_unknown" msgid="6058852665954511124">"Kurasa"</string>
- <string name="generating_print_job" msgid="3119608742651698916">"Inaleta kazi ya kuchapisha"</string>
+ <string name="generating_print_job" msgid="3119608742651698916">"Inazanzisha kazi ya kuchapisha"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Hifadhi kama PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Printa zote..."</string>
<string name="print_dialog" msgid="32628687461331979">"Chapisha mazungumzo"</string>
@@ -63,7 +63,7 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hakuna muunganisho kwa printa"</string>
<string name="reason_unknown" msgid="5507940196503246139">"haijulikani"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - haipatikani"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuleta kazi ya kuchapisha"</string>
+ <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuunda kazi ya kuchapisha"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Nyeusi na Nyeupe"</item>
<item msgid="2762241247228983754">"Rangi"</item>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 59c3ccf..99f36f9 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -17,8 +17,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Prostredie"</string>
- <string name="bugreport_finished_title" msgid="2293711546892863898">"Hlásenie o chybách bolo vytvorené"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Hlásenie o chybách môžete zdielať klepnutím"</string>
+ <string name="bugreport_finished_title" msgid="2293711546892863898">"Správa o chybách sa zaznamenala"</string>
+ <string name="bugreport_finished_text" msgid="3559904746859400732">"Dotykom môžete zdieľať správu o chybách"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
</resources>
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index f8f064a..69c6159 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/systemui/EventLogTags.logtags
+LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_PACKAGE_NAME := SystemUI
@@ -14,6 +15,11 @@
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_RESOURCE_DIR := \
+ frameworks/base/packages/Keyguard/res \
+ $(LOCAL_PATH)/res
+LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.keyguard
+
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3424eed..d371d70 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -89,11 +89,20 @@
<!-- Keyguard -->
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+ <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
+ <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
+ <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
+ <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+ <uses-permission android:name="android.permission.TRUST_LISTENER" />
<!-- Wifi Display -->
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
<application
+ android:name=".SystemUIApplication"
android:persistent="true"
android:allowClearUserData="false"
android:allowBackup="false"
@@ -101,7 +110,11 @@
android:label="@string/app_label"
android:icon="@*android:drawable/platlogo"
android:process="com.android.systemui"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:theme="@style/systemui_theme">
+ <!-- Keep theme in sync with SystemUIApplication.onCreate().
+ Setting the theme on the application does not affect views inflated by services.
+ The application theme is set again from onCreate to take effect for those views. -->
<!-- Broadcast receiver that gets the broadcast at boot time and starts
up everything else.
@@ -258,6 +271,10 @@
</intent-filter>
</service>
+ <service
+ android:name=".keyguard.KeyguardService"
+ android:exported="true" />
+
<activity android:name=".Somnambulator"
android:label="@string/start_dreams"
android:icon="@mipmap/ic_launcher_dreams"
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 48d9722..da37803 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -6,7 +6,7 @@
public void setGlowAlpha(float);
public void setGlowScale(float);
}
--keep class com.android.systemui.recents.views.TaskIconView {
+-keep class com.android.systemui.recents.views.TaskInfoView {
public void setCircularClipRadius(float);
public float getCircularClipRadius();
}
diff --git a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
index 85f1ea2..3a47261 100644
--- a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
- <item android:drawable="@*android:drawable/list_selector_disabled_holo_dark" />
+ <item android:state_pressed="true"
+ android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
</selector>
diff --git a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
deleted file mode 100644
index 0947c6f..0000000
--- a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- This is the combined status bar / notification panel window. -->
-<com.android.systemui.statusbar.phone.StatusBarWindowView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
- android:focusable="true"
- android:descendantFocusability="afterDescendants"
- android:fitsSystemWindows="true"
- >
-
- <include layout="@layout/status_bar"
- android:layout_width="match_parent"
- android:layout_height="@*android:dimen/status_bar_height"
- />
-
-
- <com.android.systemui.statusbar.phone.PanelHolder
- android:id="@+id/panel_holder"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginTop="@*android:dimen/status_bar_height"
- >
- <include layout="@layout/status_bar_expanded"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="wrap_content"
- android:layout_gravity="start|top"
- />
- <include layout="@layout/quick_settings"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="wrap_content"
- android:layout_gravity="end|top"
- />
- </com.android.systemui.statusbar.phone.PanelHolder>
-</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 5488a87..a6fb443 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -169,6 +169,7 @@
android:scaleType="center"
android:visibility="gone"
android:contentDescription="@string/accessibility_camera_button"
+ systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 8297878..7f64032 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -21,6 +21,21 @@
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
+ <com.android.systemui.recents.views.TaskInfoView
+ android:id="@+id/task_view_info_pane"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"
+ android:background="#e6444444">
+ <Button
+ android:id="@+id/task_view_app_info_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="20dp"
+ android:layout_marginEnd="20dp"
+ android:layout_gravity="top|center_horizontal"
+ android:text="@string/recents_app_info_button_label" />
+ </com.android.systemui.recents.views.TaskInfoView>
<com.android.systemui.recents.views.TaskBarView
android:id="@+id/task_view_bar"
android:layout_width="match_parent"
@@ -31,15 +46,15 @@
android:id="@+id/application_icon"
android:layout_width="@dimen/recents_task_view_application_icon_size"
android:layout_height="@dimen/recents_task_view_application_icon_size"
- android:layout_gravity="center_vertical|left"
+ android:layout_gravity="center_vertical|start"
android:padding="8dp" />
<TextView
android:id="@+id/activity_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|left"
- android:layout_marginLeft="@dimen/recents_task_view_application_icon_size"
- android:layout_marginRight="@dimen/recents_task_view_activity_icon_size"
+ android:layout_marginStart="@dimen/recents_task_view_application_icon_size"
+ android:layout_marginEnd="@dimen/recents_task_view_activity_icon_size"
android:textSize="24sp"
android:textColor="#ffffffff"
android:text="@string/recents_empty_message"
@@ -52,7 +67,7 @@
android:id="@+id/activity_icon"
android:layout_width="@dimen/recents_task_view_activity_icon_size"
android:layout_height="@dimen/recents_task_view_activity_icon_size"
- android:layout_gravity="center_vertical|right"
+ android:layout_gravity="center_vertical|end"
android:padding="12dp"
android:visibility="invisible" />
</com.android.systemui.recents.views.TaskBarView>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index ea6be1b..1b35537 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -27,7 +27,6 @@
android:orientation="vertical"
android:focusable="true"
android:descendantFocusability="afterDescendants"
- android:fitsSystemWindows="true"
>
<ImageView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index a7ec064..8f4417e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -36,6 +36,14 @@
android:layout_gravity="bottom"
/>
+ <ViewStub android:id="@+id/keyguard_flip_stub"
+ android:layout="@layout/status_bar_flip_button"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:layout_gravity="right|top"
+ android:layout_marginTop="@*android:dimen/status_bar_height"
+ android:visibility="gone" />
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -49,6 +57,10 @@
android:layout_height="@dimen/notification_panel_header_height"
/>
+ <include
+ layout="@layout/keyguard_status_view"
+ android:visibility="gone" />
+
<TextView
android:id="@+id/emergency_calls_only"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9aa7cfd..56523db 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -81,29 +81,10 @@
android:src="@drawable/ic_notify_clear"
android:background="@drawable/ic_notify_button_bg"
android:contentDescription="@string/accessibility_clear_all"
- />
+ />
- <FrameLayout android:id="@+id/settings_button_holder"
+ <include layout="@layout/status_bar_flip_button"
android:layout_width="50dp"
android:layout_height="50dp"
- android:layout_marginStart="12dp"
- >
- <ImageView android:id="@+id/settings_button"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:scaleType="center"
- android:src="@drawable/ic_notify_settings"
- android:background="@drawable/ic_notify_button_bg"
- android:contentDescription="@string/accessibility_desc_quick_settings"
- />
- <ImageView android:id="@+id/notification_button"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:scaleType="center"
- android:src="@drawable/ic_notifications"
- android:background="@drawable/ic_notify_button_bg"
- android:visibility="gone"
- android:contentDescription="@string/accessibility_notifications_button"
- />
- </FrameLayout>
+ android:layout_marginStart="12dp" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_flip_button.xml b/packages/SystemUI/res/layout/status_bar_flip_button.xml
new file mode 100644
index 0000000..db672ea
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_flip_button.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/settings_button_holder"
+ android:layout_width="50dp"
+ android:layout_height="50dp">
+ <ImageView android:id="@+id/settings_button"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:scaleType="center"
+ android:src="@drawable/ic_notify_settings"
+ android:background="@drawable/ic_notify_button_bg"
+ android:contentDescription="@string/accessibility_desc_quick_settings" />
+ <ImageView android:id="@+id/notification_button"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:scaleType="center"
+ android:src="@drawable/ic_notifications"
+ android:background="@drawable/ic_notify_button_bg"
+ android:visibility="gone"
+ android:contentDescription="@string/accessibility_notifications_button" />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
new file mode 100644
index 0000000..5d2f330
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -0,0 +1,52 @@
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<!-- Extends FrameLayout -->
+<com.android.systemui.statusbar.NotificationOverflowContainer
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <com.android.systemui.statusbar.LatestItemView
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_marginTop="@dimen/notification_divider_height"
+ android:focusable="true"
+ android:clickable="true"
+ android:background="@*android:drawable/notification_quantum_bg_dim"
+ >
+ <TextView
+ android:id="@+id/more_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:gravity="center_horizontal"
+ android:textColor="@color/keyguard_overflow_content_color"
+ android:textAllCaps="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+ <com.android.systemui.statusbar.NotificationOverflowIconsView
+ android:id="@+id/overflow_icons_view"
+ android:layout_gravity="end|center_vertical"
+ android:gravity="end"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:layout_width="120dp"
+ android:layout_height="wrap_content"
+ />
+ </com.android.systemui.statusbar.LatestItemView>
+</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index e74e568..d61d8b9 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -32,6 +32,7 @@
android:layout_marginTop="@dimen/notification_divider_height"
android:focusable="true"
android:clickable="true"
+ android:background="@*android:drawable/notification_quantum_bg"
>
<com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expanded"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 2b56618..9176d24 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -20,32 +20,29 @@
<!-- This is the combined status bar / notification panel window. -->
<com.android.systemui.statusbar.phone.StatusBarWindowView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:focusable="true"
- android:descendantFocusability="afterDescendants"
- android:fitsSystemWindows="true"
- android:background="@android:color/transparent"
- >
+ android:descendantFocusability="afterDescendants">
<include layout="@layout/status_bar"
android:layout_width="match_parent"
- android:layout_height="@*android:dimen/status_bar_height"
- />
+ android:layout_height="@*android:dimen/status_bar_height" />
<com.android.systemui.statusbar.phone.PanelHolder
android:id="@+id/panel_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
- >
+ android:layout_marginTop="@dimen/panel_holder_padding_top"
+ android:layout_marginBottom="@*android:dimen/navigation_bar_height">
<include layout="@layout/status_bar_expanded"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
+ android:layout_width="@dimen/notification_panel_width"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|top" />
<ViewStub android:id="@+id/quick_settings_stub"
android:layout="@layout/quick_settings"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
+ android:layout_width="@dimen/notification_panel_width"
+ android:layout_height="match_parent" />
</com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/user_switcher_host.xml b/packages/SystemUI/res/layout/user_switcher_host.xml
new file mode 100644
index 0000000..bc56cf6
--- /dev/null
+++ b/packages/SystemUI/res/layout/user_switcher_host.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<!-- FrameLayout -->
+<com.android.systemui.settings.UserSwitcherHostView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#dd000000">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@*android:dimen/volume_panel_top"
+ android:background="@*android:drawable/dialog_full_holo_dark">
+ <ListView android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:listitem="@layout/user_switcher_item"/>
+ </FrameLayout>
+</com.android.systemui.settings.UserSwitcherHostView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/user_switcher_item.xml b/packages/SystemUI/res/layout/user_switcher_item.xml
new file mode 100644
index 0000000..43a85e7
--- /dev/null
+++ b/packages/SystemUI/res/layout/user_switcher_item.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ android:orientation="horizontal"
+ tools:context=".settings.UserSwitcherDialog">
+ <ImageView
+ android:layout_width="64dp"
+ android:layout_height="match_parent"
+ android:id="@+id/user_picture"
+ tools:src="@drawable/dessert_zombiegingerbread"/>
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:id="@+id/user_name"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:padding="8dp"
+ android:gravity="center_vertical"
+ tools:text="Hiroshi Lockheimer"
+ />
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 98d132a..a3cabc2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Soek"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Gly links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Kennisgewing versteek"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d kennisgewings versteek"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Raak om te wys"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 2e116d0..5dbc618 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"ፍለጋ"</string>
<string name="description_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string>
<string name="description_direction_left" msgid="7207478719805562165">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ግራ አንሸራትት።"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"ማሳወቂያ ተደብቋል"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d ማሳወቂያዎች ተደብቀዋል"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"ለማሳየት ነካ ያድርጉ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 596f612..715aadc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
<string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"تم إخفاء الإشعار"</item>
+ <item quantity="other" msgid="7388721375827338153">"تم إخفاء %d من الإشعارات"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"المس للعرض"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 335c33a..c9ca1f0 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Търсене"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Плъзнете нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Плъзнете наляво за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Известието е скрито"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d известия са скрити"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Докоснете за показване"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e79e094..62d4c72 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Fes lliscar el dit cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notificació oculta"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notificacions ocultes"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca per mostrar-ho."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 60bbe3b..e96f8cf 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Přejeďte prstem doleva: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Oznámení bylo skryto"</item>
+ <item quantity="other" msgid="7388721375827338153">"Skrytá oznámení: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Oznámení zobrazíte kliknutím"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 86c1eb96..5b4a41c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Søgning"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Glid til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Underretningen er skjult"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d underretninger er skjult"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tryk for at vise"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c8cb0a4..9557897 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Suche"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links schieben"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Benachrichtigung ausgeblendet"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d Benachrichtigungen ausgeblendet"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Zum Ansehen tippen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 79025b6..796b80d 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Κύλιση προς τα αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Έγινε απόκρυψη της ειδοποίησης"</item>
+ <item quantity="other" msgid="7388721375827338153">"Έγινε απόκρυψη %d ειδοποιήσεων"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Αγγίξτε για εμφάνιση"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 338c8ac..77262d5 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Search"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notification hidden"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notifications hidden"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touch to show"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 338c8ac..77262d5 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Search"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notification hidden"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notifications hidden"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touch to show"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 89fe58b..f195f6a 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notificación oculta"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notificaciones ocultas"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca para mostrar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f2a9850..d6ddd63 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notification oculta"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notificaciones ocultas"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca para mostrar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index b734fa8..ab9b18e 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -209,4 +209,7 @@
<string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for zen_mode_notification_title:other (7388721375827338153) -->
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Puudutage kuvamiseks"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5780a57..bf295f2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
<string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"اعلان پنهان شده"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d اعلان پنهان شده"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"برای نمایش لمس کنید"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4809741..0fa764e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Ilmoitus piilotettu"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d ilmoitusta piilotettu"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Näytä koskettamalla"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 36b54ce..2a2ed5e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Recherche"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Faire glisser le doigt vers le haut : <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Faites glisser votre doigt vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notification masquée"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notifications masquées"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touchez pour afficher la notification"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5b81975..278e580 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Faites glisser vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notification masquée"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notifications masquées"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Appuyer pour afficher"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9be9550..139ae83 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्लाइड करें."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्लाइड करें."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"सूचना छिपी हुई है"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d सूचनाएं छिपी हुई हैं"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"दिखाने के लिए स्पर्श करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 21d6ef5..646c391 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Obavijest je skrivena"</item>
+ <item quantity="other" msgid="7388721375827338153">"Broj skrivenih obavijesti: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dodirnite za prikaz"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8e6ee4f..ea1caec 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Keresés"</string>
<string name="description_direction_up" msgid="7169032478259485180">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa felfelé."</string>
<string name="description_direction_left" msgid="7207478719805562165">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa balra."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Értesítés elrejtve"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d értesítés elrejtve"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"A megtekintéshez érintse meg"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index a787983..ca185f6 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Որոնել"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Սահեցրեք վերև <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Սահեցրեք ձախ` <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Ծանուցումը թաքցված է"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d ծանուցում թաքցված է"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Հպեք՝ ցուցադրելու համար"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 13fc534..d6dacd6 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Pemberitahuan disembunyikan"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d pemberitahuan disembunyikan"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Sentuh untuk menampilkan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 289d6c6..5a6d93b 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notifica nascosta"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notifiche nascoste"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tocca per visualizzare"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 798e8c3..3650bfe 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string>
<string name="description_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"הסט שמאלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"ההודעה הוסתרה"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d הודעות הוסתרו"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"גע כדי להציג"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c5070a8..97a3083 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
<string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"通知が非表示"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d件の通知が非表示"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"表示するにはタップします"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index bbdce19..d893f51 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"ძიება"</string>
<string name="description_direction_up" msgid="7169032478259485180">"გაასრიალეთ ზემოთ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
<string name="description_direction_left" msgid="7207478719805562165">"გაასრიალეთ მარცხნივ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"შეტყობინება დამალულია"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d შეტყობინება დამალულია"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"შეეხეთ საჩვენებლად"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 61ca77d..ed0b874 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
<string name="description_direction_up" msgid="7169032478259485180">"រុញឡើងលើដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
<string name="description_direction_left" msgid="7207478719805562165">"រុញទៅឆ្វេងដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"បានលាក់ការជូនដំណឹង"</item>
+ <item quantity="other" msgid="7388721375827338153">"បានលាក់ការជូនដំណឹង %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"ប៉ះដើម្បីបង្ហាញ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8108daa..56f0278 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"검색"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"알림 숨김"</item>
+ <item quantity="other" msgid="7388721375827338153">"알림 %d개 숨김"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"표시하려면 터치"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index c2e5990..b0e4b15 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"ຊອກຫາ"</string>
<string name="description_direction_up" msgid="7169032478259485180">"ເລື່ອນຂຶ້ນເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"ເລື່ອນໄປທາງຊ້າຍເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"ເຊື່ອງການແຈ້ງເຕືອນແລ້ວ"</item>
+ <item quantity="other" msgid="7388721375827338153">"ເຊື່ອງ %d ການແຈ້ງເຕືອນແລ້ວ"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"ແຕະເພື່ອສະແດງ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 1d8b051..adbba12 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Pranešimas paslėptas"</item>
+ <item quantity="other" msgid="7388721375827338153">"Paslėpta pranešimų: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Palieskite, kad būtų rodoma"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 603fa1a..42bdbc8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Paziņojums paslēpts"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d paziņojumi paslēpti"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Pieskarieties, lai rādītu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 110cfd2..c56d51a 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Хайх"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-г гулсуулах."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> хийх зүүнлүү гулсуулах."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Мэдэгдлийг нуусан"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d мэдэгдлийг нуусан"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Харуулахын тулд хүрнэ үү"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 62c90ab..5ca5082 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Carian"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Luncurkan ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Luncurkan ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Pemberitahuan disembunyikan"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d pemberitahuan disembunyikan"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Sentuh untuk menunjukkan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0e914ea..7f4d0d1 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Søk"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Dra til venstre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Varselet er skjult"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d varsler er skjult"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Trykk for å vise"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 032fa34..4e1c811 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Melding verborgen"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d meldingen verborgen"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Raak aan om weer te geven"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c21230c..5b360c9 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Szukaj"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Przesuń w górę: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Przesuń w lewo: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Powiadomienie ukryte"</item>
+ <item quantity="other" msgid="7388721375827338153">"Ukryte powiadomienia: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dotknij, by zobaczyć"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 771daf2..5e182f6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Deslize para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notificação oculta"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notificações ocultas"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toque para mostrar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b643bae..c88faf1 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para cima."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para a esquerda."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notificação oculta"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d notificações ocultas"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toque para mostrar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 33cb355..7f17a23 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -388,4 +388,8 @@
<skip />
<!-- no translation found for description_direction_left (7207478719805562165) -->
<skip />
+ <!-- no translation found for zen_mode_notification_title:one (7809876956258040354) -->
+ <!-- no translation found for zen_mode_notification_title:other (7388721375827338153) -->
+ <!-- no translation found for zen_mode_notification_text (8336623711388065713) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87f9c0c..c37fda5 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Notificare ascunsă"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d de notificări ascunse"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Atingeți pentru a afișa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e79a0dd..aff253c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -213,4 +213,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Оповещение скрыто"</item>
+ <item quantity="other" msgid="7388721375827338153">"Скрыто оповещений: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Нажмите, чтобы открыть"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index d39c8bd..5e5ae9b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Prejdite prstom doľava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Upozornenie bolo skryté"</item>
+ <item quantity="other" msgid="7388721375827338153">"Skryté upozornenia: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Upozornenie zobrazíte dotykom"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9d57586..2d562da 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Iskanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Povlecite navzgor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Povlecite v levo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Obvestilo je skrito"</item>
+ <item quantity="other" msgid="7388721375827338153">"Skritih je toliko obvestil: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dotaknite se za prikaz"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 89bc3c5..97743ad 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Обавештење је сакривено"</item>
+ <item quantity="other" msgid="7388721375827338153">"Сакривена обавештења: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Додирните за приказ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1b47be5..4ce20e9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Sök"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Aviseringen har dolts"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d aviseringar har dolts"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tryck här om du vill visa aviseringar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3702196..5b9a4ad 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -207,4 +207,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Tafuta"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Sogeza kushoto kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Arifa imefichwa"</item>
+ <item quantity="other" msgid="7388721375827338153">"Arifa %d zimefichwa"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Gusa ili zionekane"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index b77f1e0..440ead6 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -30,5 +30,5 @@
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
<!-- Enable the "flip settings" panel -->
- <bool name="config_hasFlipSettingsPanel">false</bool>
+ <bool name="config_hasFlipSettingsPanel">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 45f6af3..b4fafec 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -24,8 +24,8 @@
<dimen name="notification_panel_margin_left">16dp</dimen>
<!-- Gravity for the notification & quick settings panels -->
- <!-- 0x800033 = start|top ; 0x800035 = end|top -->
- <integer name="notification_panel_layout_gravity">0x800033</integer>
+ <!-- 0x31 = top|center_horizontal ; 0x800035 = end|top -->
+ <integer name="notification_panel_layout_gravity">0x31</integer>
<integer name="settings_panel_layout_gravity">0x800035</integer>
<!-- Diameter of outer shape drawable shown in navbar search-->
@@ -41,9 +41,8 @@
<dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
<dimen name="status_bar_recents_thumbnail_height">177dp</dimen>
- <!-- On tablet-sized devices, we allocate the rightmost third(ish) of the draggable status bar
- to quick settings. -->
- <item type="dimen" name="settings_panel_dragzone_fraction">35%</item>
+ <!-- On tablets, panels drop from the statusbar instead of overlapping it. -->
+ <dimen name="panel_holder_padding_top">@*android:dimen/status_bar_height</dimen>
<!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
<item type="dimen" name="notification_panel_min_height_frac">40%</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0188563..74edb61 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
<string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
<string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"ซ่อนการแจ้งเตือนแล้ว"</item>
+ <item quantity="other" msgid="7388721375827338153">"ซ่อน %d การแจ้งเตือนแล้ว"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"แตะเพื่อแสดง"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d7502cb..3ac4cd5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Mag-slide pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Nakatago ang notification"</item>
+ <item quantity="other" msgid="7388721375827338153">"Nakatago ang %d (na) notification"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Pindutin upang ipakita"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f56293b..f38c86a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Bildirim gizli"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d bildirim gizli"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Görüntülemek için dokunun"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index df94b26..54e7ca1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Сповіщення сховано"</item>
+ <item quantity="other" msgid="7388721375827338153">"Сховано сповіщень: %d"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Торкніться, щоб показати"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 471cbd3..ade5fe1 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Thông báo ẩn"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d thông báo ẩn"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Chạm để hiển thị"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7fb5868..cbb1496 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"搜索"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"向左滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"已隐藏通知"</item>
+ <item quantity="other" msgid="7388721375827338153">"已隐藏%d条通知"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"触摸即可显示"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d4defa4..b6d438c 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"已隱藏通知"</item>
+ <item quantity="other" msgid="7388721375827338153">"已隱藏 %d 則通知"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"輕觸即可顯示"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 163ef2a..1c4cb4a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -211,4 +211,9 @@
<string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"已隱藏通知"</item>
+ <item quantity="other" msgid="7388721375827338153">"已隱藏 %d 則通知"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"輕觸即可顯示"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 92e3382..cbb6c09 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -209,4 +209,9 @@
<string name="description_target_search" msgid="3091587249776033139">"Sesha"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Shelelisela ngenhla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Shelelisela ngakwesokunxele ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <plurals name="zen_mode_notification_title">
+ <item quantity="one" msgid="7809876956258040354">"Isaziso sifihliwe"</item>
+ <item quantity="other" msgid="7388721375827338153">"%d izaziso zifihliwe"</item>
+ </plurals>
+ <string name="zen_mode_notification_text" msgid="8336623711388065713">"Thinta ukuze ubonise"</string>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 5cf0453..59e8360 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,7 +31,8 @@
<drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
<drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
<drawable name="notification_header_bg">#FF000000</drawable>
- <color name="notification_panel_scrim_color">#B0000000</color>
+ <color name="notification_panel_scrim_color">#A0000000</color>
+ <color name="notification_panel_scrim_color_keyguard">#80000000</color>
<color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
<color name="batterymeter_charge_color">#FFFFFFFF</color>
<color name="batterymeter_bolt_color">#FFFFFFFF</color>
@@ -45,4 +46,7 @@
<!-- Tint color for active Quick Settings icons. -->
<color name="ic_qs_on">#ffffffff</color>
+
+ <!-- Tint color for the content on the notification overflow card. -->
+ <color name="keyguard_overflow_content_color">#ff666666</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 672c1d0..73e3e05 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -114,5 +114,13 @@
<integer name="recents_filter_animate_new_views_min_duration">125</integer>
<!-- The min animation duration for animating views that are newly visible. -->
<integer name="recents_animate_task_bar_enter_duration">200</integer>
+ <!-- The animation duration for animating in the info pane. -->
+ <integer name="recents_animate_task_view_info_pane_duration">150</integer>
+ <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
+ <integer name="recents_max_task_stack_view_dim">96</integer>
+
+ <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
+ card. -->
+ <integer name="keyguard_max_notification_count">4</integer>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2c8f9a1..e7959ab 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -83,7 +83,7 @@
<dimen name="notification_mid_height">128dp</dimen>
<!-- Height of a small notification in the status bar plus glow, padding, etc -->
- <dimen name="notification_row_min_height">70dp</dimen>
+ <dimen name="notification_row_min_height">68dp</dimen>
<!-- Height of a large notification in the status bar plus glow, padding, etc -->
<dimen name="notification_row_max_height">260dp</dimen>
@@ -98,7 +98,7 @@
<dimen name="status_bar_icon_padding">0dp</dimen>
<!-- half the distance between notifications in the panel -->
- <dimen name="notification_divider_height">3dp</dimen>
+ <dimen name="notification_divider_height">2dp</dimen>
<!-- Notification drawer tuning parameters (phone UI) -->
<!-- Initial velocity of the shade when expanding on its own -->
@@ -167,6 +167,9 @@
<!-- Extra space above the clock in the panel -->
<dimen name="notification_panel_header_padding_top">0dp</dimen>
+ <!-- Extra space above the panel holder -->
+ <dimen name="panel_holder_padding_top">0dp</dimen>
+
<!-- Layout parameters for the notification panel -->
<dimen name="notification_panel_margin_bottom">0dp</dimen>
<dimen name="notification_panel_margin_left">0dp</dimen>
@@ -236,6 +239,12 @@
<!-- The size of the activity icon in the recents task view. -->
<dimen name="recents_task_view_activity_icon_size">60dp</dimen>
+ <!-- The radius of the rounded corners on a task view. -->
+ <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
+
+ <!-- The amount of space a user has to scroll to dismiss any info panes. -->
+ <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
+
<!-- Used to calculate the translation animation duration, the expected amount of movement
in dps over one second of time. -->
<dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
@@ -257,4 +266,7 @@
<!-- Width of the zen mode interstitial dialog. -->
<dimen name="zen_mode_dialog_width">320dp</dimen>
+
+ <!-- Camera affordance drag distance -->
+ <dimen name="camera_drag_distance">100dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ad10545..73e5e19 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -509,6 +509,8 @@
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
<string name="recents_empty_message">RECENTS</string>
+ <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
+ <string name="recents_app_info_button_label">Application Info</string>
<!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
@@ -534,4 +536,9 @@
</plurals>
<!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
<string name="zen_mode_notification_text">Touch to show</string>
+
+ <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
+ <plurals name="keyguard_more_overflow_text">
+ <item quantity="other">%d more</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 0ece8e0..8ab646d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -168,5 +168,7 @@
<!-- Note: must be dp to fit in status bar -->
<item name="android:textSize">14dp</item>
</style>
-
+
+ <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
new file mode 100644
index 0000000..0f55683
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.app.Application;
+import android.content.res.Configuration;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Application class for SystemUI.
+ */
+public class SystemUIApplication extends Application {
+
+ private static final String TAG = "SystemUIService";
+ private static final boolean DEBUG = false;
+
+ /**
+ * The classes of the stuff to start.
+ */
+ private final Class<?>[] SERVICES = new Class[] {
+ com.android.systemui.keyguard.KeyguardViewMediator.class,
+ com.android.systemui.recent.Recents.class,
+ com.android.systemui.statusbar.SystemBars.class,
+ com.android.systemui.usb.StorageNotification.class,
+ com.android.systemui.power.PowerUI.class,
+ com.android.systemui.media.RingtonePlayer.class,
+ com.android.systemui.settings.SettingsUI.class,
+ };
+
+ /**
+ * Hold a reference on the stuff we start.
+ */
+ private final SystemUI[] mServices = new SystemUI[SERVICES.length];
+ private boolean mServicesStarted;
+ private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ // Set the application theme that is inherited by all services. Note that setting the
+ // application theme in the manifest does only work for activities. Keep this in sync with
+ // the theme set there.
+ setTheme(R.style.systemui_theme);
+ }
+
+ /**
+ * Makes sure that all the SystemUI services are running. If they are already running, this is a
+ * no-op. This is needed to conditinally start all the services, as we only need to have it in
+ * the main process.
+ *
+ * <p>This method must only be called from the main thread.</p>
+ */
+ public void startServicesIfNeeded() {
+ if (mServicesStarted) {
+ return;
+ }
+ final int N = SERVICES.length;
+ for (int i=0; i<N; i++) {
+ Class<?> cl = SERVICES[i];
+ if (DEBUG) Log.d(TAG, "loading: " + cl);
+ try {
+ mServices[i] = (SystemUI)cl.newInstance();
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ } catch (InstantiationException ex) {
+ throw new RuntimeException(ex);
+ }
+ mServices[i].mContext = this;
+ mServices[i].mComponents = mComponents;
+ if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
+ mServices[i].start();
+ }
+ mServicesStarted = true;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ if (mServicesStarted) {
+ int len = mServices.length;
+ for (int i = 0; i < len; i++) {
+ mServices[i].onConfigurationChanged(newConfig);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getComponent(Class<T> interfaceType) {
+ return (T) mComponents.get(interfaceType);
+ }
+
+ public SystemUI[] getServices() {
+ return mServices;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index ca5f7d1..05e5f6b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -18,80 +18,35 @@
import android.app.Service;
import android.content.Intent;
-import android.content.res.Configuration;
import android.os.IBinder;
-import android.util.Log;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.HashMap;
public class SystemUIService extends Service {
- private static final String TAG = "SystemUIService";
-
- /**
- * The classes of the stuff to start.
- */
- private final Class<?>[] SERVICES = new Class[] {
- com.android.systemui.recent.Recents.class,
- com.android.systemui.statusbar.SystemBars.class,
- com.android.systemui.usb.StorageNotification.class,
- com.android.systemui.power.PowerUI.class,
- com.android.systemui.media.RingtonePlayer.class,
- com.android.systemui.settings.SettingsUI.class,
- };
-
- /**
- * Hold a reference on the stuff we start.
- */
- private final SystemUI[] mServices = new SystemUI[SERVICES.length];
@Override
public void onCreate() {
- HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
- final int N = SERVICES.length;
- for (int i=0; i<N; i++) {
- Class<?> cl = SERVICES[i];
- Log.d(TAG, "loading: " + cl);
- try {
- mServices[i] = (SystemUI)cl.newInstance();
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(ex);
- } catch (InstantiationException ex) {
- throw new RuntimeException(ex);
- }
- mServices[i].mContext = this;
- mServices[i].mComponents = components;
- Log.d(TAG, "running: " + mServices[i]);
- mServices[i].start();
- }
+ super.onCreate();
+ ((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- for (SystemUI ui: mServices) {
- ui.onConfigurationChanged(newConfig);
- }
- }
-
- /**
- * Nobody binds to us.
- */
- @Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
if (args == null || args.length == 0) {
- for (SystemUI ui: mServices) {
+ for (SystemUI ui: services) {
pw.println("dumping service: " + ui.getClass().getName());
ui.dump(fd, pw, args);
}
} else {
String svc = args[0];
- for (SystemUI ui: mServices) {
+ for (SystemUI ui: services) {
String name = ui.getClass().getName();
if (name.endsWith(svc)) {
ui.dump(fd, pw, args);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
similarity index 65%
rename from packages/Keyguard/src/com/android/keyguard/KeyguardService.java
rename to packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 36b2446..41c0e78 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2014 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.
@@ -11,18 +11,13 @@
* 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.
+ * limitations under the License
*/
-package com.android.keyguard;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
+package com.android.systemui.keyguard;
import android.app.Service;
import android.content.Intent;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -30,23 +25,25 @@
import android.util.Log;
import android.view.MotionEvent;
-import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.SystemUIApplication;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
+
private KeyguardViewMediator mKeyguardViewMediator;
@Override
public void onCreate() {
- if (mKeyguardViewMediator == null) {
- mKeyguardViewMediator = new KeyguardViewMediator(
- KeyguardService.this, new LockPatternUtils(KeyguardService.this));
- }
- Log.v(TAG, "onCreate()");
+ ((SystemUIApplication) getApplication()).startServicesIfNeeded();
+ mKeyguardViewMediator =
+ ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
}
@Override
@@ -54,11 +51,6 @@
return mBinder;
}
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- // TODO
- }
-
void checkPermission() {
if (getBaseContext().checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
Log.w(TAG, "Caller needs permission '" + PERMISSION + "' to call " + Debug.getCaller());
@@ -68,84 +60,148 @@
}
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
+
+ private boolean mIsOccluded;
+
+ @Override
public boolean isShowing() {
return mKeyguardViewMediator.isShowing();
}
+
+ @Override
public boolean isSecure() {
return mKeyguardViewMediator.isSecure();
}
- public boolean isShowingAndNotHidden() {
- return mKeyguardViewMediator.isShowingAndNotHidden();
+
+ @Override
+ public boolean isShowingAndNotOccluded() {
+ return mKeyguardViewMediator.isShowingAndNotOccluded();
}
+
+ @Override
public boolean isInputRestricted() {
return mKeyguardViewMediator.isInputRestricted();
}
+
+ @Override
public void verifyUnlock(IKeyguardExitCallback callback) {
+ checkPermission();
mKeyguardViewMediator.verifyUnlock(callback);
}
+
+ @Override
public void keyguardDone(boolean authenticated, boolean wakeup) {
checkPermission();
mKeyguardViewMediator.keyguardDone(authenticated, wakeup);
}
- public void setHidden(boolean isHidden) {
+
+ @Override
+ public int setOccluded(boolean isOccluded) {
checkPermission();
- mKeyguardViewMediator.setHidden(isHidden);
+ synchronized (this) {
+ int result;
+ if (isOccluded && mKeyguardViewMediator.isShowing()
+ && !mIsOccluded) {
+ result = IKeyguardServiceConstants
+ .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS;
+ } else if (!isOccluded && mKeyguardViewMediator.isShowing()
+ && mIsOccluded) {
+ result = IKeyguardServiceConstants
+ .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS;
+ } else {
+ result = IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
+ }
+ if (mIsOccluded != isOccluded) {
+ mKeyguardViewMediator.setOccluded(isOccluded);
+
+ // Cache the value so we always have a fresh view in whether Keyguard is occluded.
+ // If we would just call mKeyguardViewMediator.isOccluded(), this might be stale
+ // because that value gets updated in another thread.
+ mIsOccluded = isOccluded;
+ }
+ return result;
+ }
}
+
+ @Override
public void dismiss() {
+ checkPermission();
mKeyguardViewMediator.dismiss();
}
+
+ @Override
public void onDreamingStarted() {
checkPermission();
mKeyguardViewMediator.onDreamingStarted();
}
+
+ @Override
public void onDreamingStopped() {
checkPermission();
mKeyguardViewMediator.onDreamingStopped();
}
+
+ @Override
public void onScreenTurnedOff(int reason) {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOff(reason);
}
+
+ @Override
public void onScreenTurnedOn(IKeyguardShowCallback callback) {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOn(callback);
}
+
+ @Override
public void setKeyguardEnabled(boolean enabled) {
checkPermission();
mKeyguardViewMediator.setKeyguardEnabled(enabled);
}
+
+ @Override
public boolean isDismissable() {
return mKeyguardViewMediator.isDismissable();
}
+
+ @Override
public void onSystemReady() {
checkPermission();
mKeyguardViewMediator.onSystemReady();
}
+
+ @Override
public void doKeyguardTimeout(Bundle options) {
checkPermission();
mKeyguardViewMediator.doKeyguardTimeout(options);
}
+
+ @Override
public void setCurrentUser(int userId) {
checkPermission();
mKeyguardViewMediator.setCurrentUser(userId);
}
+
+ @Override
public void showAssistant() {
checkPermission();
- mKeyguardViewMediator.showAssistant();
}
+
+ @Override
public void dispatch(MotionEvent event) {
checkPermission();
- mKeyguardViewMediator.dispatch(event);
}
+
+ @Override
public void launchCamera() {
checkPermission();
- mKeyguardViewMediator.launchCamera();
}
+
+ @Override
public void onBootCompleted() {
checkPermission();
mKeyguardViewMediator.onBootCompleted();
}
};
-
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
similarity index 85%
rename from packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
rename to packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 354d13f..bb39d36 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2014 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.
@@ -11,15 +11,10 @@
* 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.
+ * limitations under the License
*/
-package com.android.keyguard;
-
-import com.android.internal.policy.IKeyguardExitCallback;
-import com.android.internal.policy.IKeyguardShowCallback;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+package com.android.systemui.keyguard;
import android.app.Activity;
import android.app.ActivityManagerNative;
@@ -50,17 +45,31 @@
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
-import android.view.MotionEvent;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
+import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.analytics.Session;
+import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.MultiUserAvatarCache;
+import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.analytics.KeyguardAnalytics;
+import com.android.keyguard.analytics.Session;
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
import java.io.File;
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+
/**
* Mediates requests related to the keyguard. This includes queries about the
@@ -95,15 +104,15 @@
* false, this will override all other conditions for turning on the keyguard.
*
* Threading and synchronization:
- * This class is created by the initialization routine of the {@link WindowManagerPolicy},
+ * This class is created by the initialization routine of the {@link android.view.WindowManagerPolicy},
* and runs on its thread. The keyguard UI is created from that thread in the
* constructor of this class. The apis may be called from other threads, including the
* {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
* Therefore, methods on this class are synchronized, and any action that is pointed
- * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
+ * directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
* thread of the keyguard.
*/
-public class KeyguardViewMediator {
+public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
final static boolean DEBUG = false;
private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
@@ -124,17 +133,14 @@
private static final int KEYGUARD_DONE = 9;
private static final int KEYGUARD_DONE_DRAWING = 10;
private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
- private static final int SET_HIDDEN = 12;
+ private static final int SET_OCCLUDED = 12;
private static final int KEYGUARD_TIMEOUT = 13;
- private static final int SHOW_ASSISTANT = 14;
- private static final int DISPATCH_EVENT = 15;
- private static final int LAUNCH_CAMERA = 16;
private static final int DISMISS = 17;
/**
* The default amount of time we stay awake (used for all key input)
*/
- protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+ public static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
/**
* How long to wait after the screen turns off due to timeout before
@@ -158,13 +164,13 @@
/**
* Allow the user to expand the status bar when a SECURE keyguard is engaged
- * and {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
+ * and {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
* (private notifications will be masked).
*/
private static final boolean ENABLE_SECURE_STATUS_BAR_EXPAND = true;
/**
- * Default value of {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+ * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
*/
private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
@@ -176,7 +182,6 @@
/** The stream type that the lock sounds are tied to. */
private int mMasterStreamType;
- private Context mContext;
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
@@ -204,9 +209,9 @@
*/
private PowerManager.WakeLock mShowKeyguardWakeLock;
- private KeyguardViewManager mKeyguardViewManager;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private final KeyguardAnalytics mKeyguardAnalytics;
+ private KeyguardAnalytics mKeyguardAnalytics;
// these are protected by synchronized (this)
@@ -227,7 +232,7 @@
private boolean mShowing;
// true if the keyguard is hidden by another window
- private boolean mHidden = false;
+ private boolean mOccluded = false;
/**
* Helps remember whether the screen has turned on since the last time
@@ -272,79 +277,20 @@
private int mLockSoundStreamId;
/**
- * Tracks value of {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+ * Tracks value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
*/
private boolean mAllowNotificationsWhenSecure;
/**
* The volume applied to the lock/unlock sounds.
*/
- private final float mLockSoundVolume;
+ private float mLockSoundVolume;
/**
* For managing external displays
*/
private KeyguardDisplayManager mKeyguardDisplayManager;
- /**
- * Cache of avatar drawables, for use by KeyguardMultiUserAvatar.
- */
- private static MultiUserAvatarCache sMultiUserAvatarCache = new MultiUserAvatarCache();
-
- /**
- * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
- * various things.
- */
- public interface ViewMediatorCallback {
- /**
- * Reports user activity and requests that the screen stay on.
- */
- void userActivity();
-
- /**
- * Reports user activity and requests that the screen stay on for at least
- * the specified amount of time.
- * @param millis The amount of time in millis. This value is currently ignored.
- */
- void userActivity(long millis);
-
- /**
- * Report that the keyguard is done.
- * @param authenticated Whether the user securely got past the keyguard.
- * the only reason for this to be false is if the keyguard was instructed
- * to appear temporarily to verify the user is supposed to get past the
- * keyguard, and the user fails to do so.
- */
- void keyguardDone(boolean authenticated);
-
- /**
- * Report that the keyguard is done drawing.
- */
- void keyguardDoneDrawing();
-
- /**
- * Tell ViewMediator that the current view needs IME input
- * @param needsInput
- */
- void setNeedsInput(boolean needsInput);
-
- /**
- * Tell view mediator that the keyguard view's desired user activity timeout
- * has changed and needs to be reapplied to the window.
- */
- void onUserActivityTimeoutChanged();
-
- /**
- * Report that the keyguard is dismissable, pending the next keyguardDone call.
- */
- void keyguardDonePending();
-
- /**
- * Report when keyguard is actually gone
- */
- void keyguardGone();
- }
-
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -354,7 +300,7 @@
// ActivityManagerService) will not reconstruct the keyguard if it is already showing.
synchronized (KeyguardViewMediator.this) {
mSwitchingUser = true;
- resetStateLocked(null);
+ resetStateLocked();
adjustStatusBarLocked();
// When we switch users we want to bring the new user to the biometric unlock even
// if the current user has gone to the backup.
@@ -370,16 +316,16 @@
@Override
public void onUserRemoved(int userId) {
mLockPatternUtils.removeUser(userId);
- sMultiUserAvatarCache.clear(userId);
+ MultiUserAvatarCache.getInstance().clear(userId);
}
@Override
public void onUserInfoChanged(int userId) {
- sMultiUserAvatarCache.clear(userId);
+ MultiUserAvatarCache.getInstance().clear(userId);
}
@Override
- void onPhoneStateChanged(int phoneState) {
+ public void onPhoneStateChanged(int phoneState) {
synchronized (KeyguardViewMediator.this) {
if (TelephonyManager.CALL_STATE_IDLE == phoneState // call ending
&& !mScreenOn // screen off
@@ -394,7 +340,7 @@
doKeyguardLocked(null);
}
}
- };
+ }
@Override
public void onClockVisibilityChanged() {
@@ -423,7 +369,7 @@
+ "device isn't provisioned yet.");
doKeyguardLocked(null);
} else {
- resetStateLocked(null);
+ resetStateLocked();
}
}
}
@@ -436,7 +382,7 @@
+ "showing; need to show keyguard so user can enter sim pin");
doKeyguardLocked(null);
} else {
- resetStateLocked(null);
+ resetStateLocked();
}
}
break;
@@ -449,14 +395,14 @@
} else {
if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+ "show permanently disabled message in lockscreen.");
- resetStateLocked(null);
+ resetStateLocked();
}
}
break;
case READY:
synchronized (this) {
if (isShowing()) {
- resetStateLocked(null);
+ resetStateLocked();
}
}
break;
@@ -466,6 +412,7 @@
};
ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+
public void userActivity() {
KeyguardViewMediator.this.userActivity();
}
@@ -484,12 +431,12 @@
@Override
public void setNeedsInput(boolean needsInput) {
- mKeyguardViewManager.setNeedsInput(needsInput);
+ mStatusBarKeyguardViewManager.setNeedsInput(needsInput);
}
@Override
public void onUserActivityTimeoutChanged() {
- mKeyguardViewManager.updateUserActivityTimeout();
+ mStatusBarKeyguardViewManager.updateUserActivityTimeout();
}
@Override
@@ -513,40 +460,34 @@
mPM.userActivity(SystemClock.uptimeMillis(), false);
}
- /**
- * Construct a KeyguardViewMediator
- * @param context
- * @param lockPatternUtils optional mock interface for LockPatternUtils
- */
- public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
- mContext = context;
- mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ private void setup() {
+ mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
- mKeyguardDisplayManager = new KeyguardDisplayManager(context);
+ mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+ mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- mLockPatternUtils = lockPatternUtils != null
- ? lockPatternUtils : new LockPatternUtils(mContext);
+ mLockPatternUtils = new LockPatternUtils(mContext);
mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
// Assume keyguard is showing (unless it's disabled) until we know for sure...
mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
&& !mLockPatternUtils.isLockScreenDisabled();
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
+ mViewMediatorCallback, mLockPatternUtils);
final ContentResolver cr = mContext.getContentResolver();
if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
- mKeyguardAnalytics = new KeyguardAnalytics(context, new SessionTypeAdapter() {
+ mKeyguardAnalytics = new KeyguardAnalytics(mContext, new SessionTypeAdapter() {
@Override
public int getSessionType() {
@@ -559,9 +500,6 @@
} else {
mKeyguardAnalytics = null;
}
- mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
- mLockPatternUtils,
- mKeyguardAnalytics != null ? mKeyguardAnalytics.getCallback() : null);
mScreenOn = mPM.isScreenOn();
@@ -580,11 +518,17 @@
if (soundPath == null || mUnlockSoundId == 0) {
Log.w(TAG, "failed to load unlock sound from " + soundPath);
}
- int lockSoundDefaultAttenuation = context.getResources().getInteger(
+ int lockSoundDefaultAttenuation = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lockSoundVolumeDb);
mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
}
+ @Override
+ public void start() {
+ setup();
+ putComponent(KeyguardViewMediator.class, this);
+ }
+
/**
* Let us know that the system is ready after startup.
*/
@@ -621,9 +565,9 @@
/**
* Called to let us know the screen was turned off.
- * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
- * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
- * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+ * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER},
+ * {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
+ * {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
*/
public void onScreenTurnedOff(int why) {
synchronized (this) {
@@ -651,7 +595,7 @@
}
} else if (mShowing) {
notifyScreenOffLocked();
- resetStateLocked(null);
+ resetStateLocked();
} else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
|| (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
doKeyguardLaterLocked();
@@ -768,7 +712,7 @@
}
/**
- * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
+ * Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide
* a way for external stuff to override normal keyguard behavior. For instance
* the phone app disables the keyguard when it receives incoming calls.
*/
@@ -805,7 +749,7 @@
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
mExitSecureCallback = null;
- resetStateLocked(null);
+ resetStateLocked();
} else {
showLocked(null);
@@ -873,36 +817,41 @@
return mShowing;
}
- /**
- * Is the keyguard currently showing and not being force hidden?
- */
- public boolean isShowingAndNotHidden() {
- return mShowing && !mHidden;
+ public boolean isOccluded() {
+ return mOccluded;
}
/**
- * Notify us when the keyguard is hidden by another window
+ * Is the keyguard currently showing and not being force hidden?
*/
- public void setHidden(boolean isHidden) {
- if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
- mUpdateMonitor.sendKeyguardVisibilityChanged(!isHidden);
- mHandler.removeMessages(SET_HIDDEN);
- Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
+ public boolean isShowingAndNotOccluded() {
+ return mShowing && !mOccluded;
+ }
+
+ /**
+ * Notify us when the keyguard is occluded by another window
+ */
+ public void setOccluded(boolean isOccluded) {
+ if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
+ mUpdateMonitor.sendKeyguardVisibilityChanged(!isOccluded);
+ mHandler.removeMessages(SET_OCCLUDED);
+ Message msg = mHandler.obtainMessage(SET_OCCLUDED, (isOccluded ? 1 : 0), 0);
mHandler.sendMessage(msg);
}
/**
- * Handles SET_HIDDEN message sent by setHidden()
+ * Handles SET_OCCLUDED message sent by setOccluded()
*/
- private void handleSetHidden(boolean isHidden) {
+ private void handleSetOccluded(boolean isOccluded) {
synchronized (KeyguardViewMediator.this) {
- if (mHidden != isHidden) {
- mHidden = isHidden;
+ if (mOccluded != isOccluded) {
+ mOccluded = isOccluded;
+ mStatusBarKeyguardViewManager.setOccluded(isOccluded);
updateActivityLockScreenState();
adjustStatusBarLocked();
}
if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
- mKeyguardAnalytics.getCallback().onSetHidden(isHidden);
+ mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
}
}
}
@@ -954,7 +903,7 @@
ALLOW_NOTIFICATIONS_DEFAULT ? 1 : 0);
// if the keyguard is already showing, don't bother
- if (mKeyguardViewManager.isShowing()) {
+ if (mStatusBarKeyguardViewManager.isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
return;
}
@@ -996,8 +945,8 @@
* Dismiss the keyguard through the security layers.
*/
public void handleDismiss() {
- if (mShowing && !mHidden) {
- mKeyguardViewManager.dismiss();
+ if (mShowing && !mOccluded) {
+ mStatusBarKeyguardViewManager.dismiss();
}
}
@@ -1007,12 +956,11 @@
/**
* Send message to keyguard telling it to reset its state.
- * @param options options about how to show the keyguard
- * @see #handleReset()
+ * @see #handleReset
*/
- private void resetStateLocked(Bundle options) {
+ private void resetStateLocked() {
if (DEBUG) Log.e(TAG, "resetStateLocked");
- Message msg = mHandler.obtainMessage(RESET, options);
+ Message msg = mHandler.obtainMessage(RESET);
mHandler.sendMessage(msg);
}
@@ -1038,7 +986,7 @@
/**
* Send a message to keyguard telling it the screen just turned on.
- * @see #onScreenTurnedOn()
+ * @see #onScreenTurnedOn
* @see #handleNotifyScreenOn
*/
private void notifyScreenOnLocked(IKeyguardShowCallback result) {
@@ -1049,7 +997,7 @@
/**
* Send message to keyguard telling it to show itself
- * @see #handleShow()
+ * @see #handleShow
*/
private void showLocked(Bundle options) {
if (DEBUG) Log.d(TAG, "showLocked");
@@ -1130,7 +1078,7 @@
handleHide();
break;
case RESET:
- handleReset((Bundle) msg.obj);
+ handleReset();
break;
case VERIFY_UNLOCK:
handleVerifyUnlock();
@@ -1150,23 +1098,14 @@
case KEYGUARD_DONE_AUTHENTICATING:
keyguardDone(true, true);
break;
- case SET_HIDDEN:
- handleSetHidden(msg.arg1 != 0);
+ case SET_OCCLUDED:
+ handleSetOccluded(msg.arg1 != 0);
break;
case KEYGUARD_TIMEOUT:
synchronized (KeyguardViewMediator.this) {
doKeyguardLocked((Bundle) msg.obj);
}
break;
- case SHOW_ASSISTANT:
- handleShowAssistant();
- break;
- case DISPATCH_EVENT:
- handleDispatchEvent((MotionEvent) msg.obj);
- break;
- case LAUNCH_CAMERA:
- handleLaunchCamera();
- break;
case DISMISS:
handleDismiss();
break;
@@ -1206,21 +1145,13 @@
sendUserPresentBroadcast();
}
- protected void handleLaunchCamera() {
- mKeyguardViewManager.launchCamera();
- }
-
- protected void handleDispatchEvent(MotionEvent event) {
- mKeyguardViewManager.dispatch(event);
- }
-
private void sendUserPresentBroadcast() {
final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, currentUser);
}
/**
- * @see #keyguardDoneDrawing
+ * @see #keyguardDone
* @see #KEYGUARD_DONE_DRAWING
*/
private void handleKeyguardDoneDrawing() {
@@ -1269,7 +1200,7 @@
private void updateActivityLockScreenState() {
try {
- ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mHidden);
+ ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mOccluded);
} catch (RemoteException e) {
}
}
@@ -1287,16 +1218,12 @@
if (DEBUG) Log.d(TAG, "handleShow");
}
- mKeyguardViewManager.show(options);
+ mStatusBarKeyguardViewManager.show(options);
mShowing = true;
mKeyguardDonePending = false;
updateActivityLockScreenState();
adjustStatusBarLocked();
userActivity();
- try {
- ActivityManagerNative.getDefault().closeSystemDialogs("lock");
- } catch (RemoteException e) {
- }
// Do this at the end to not slow down display of the keyguard.
playSounds(true);
@@ -1320,7 +1247,7 @@
playSounds(false);
}
- mKeyguardViewManager.hide();
+ mStatusBarKeyguardViewManager.hide();
mShowing = false;
mKeyguardDonePending = false;
updateActivityLockScreenState();
@@ -1360,7 +1287,7 @@
}
if (DEBUG) {
- Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+ Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded
+ " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
}
@@ -1371,17 +1298,13 @@
}
/**
- * Handle message sent by {@link #resetStateLocked(Bundle)}
+ * Handle message sent by {@link #resetStateLocked}
* @see #RESET
*/
- private void handleReset(Bundle options) {
- if (options == null) {
- options = new Bundle();
- }
- options.putBoolean(KeyguardViewManager.IS_SWITCHING_USER, mSwitchingUser);
+ private void handleReset() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleReset");
- mKeyguardViewManager.reset(options);
+ mStatusBarKeyguardViewManager.reset();
}
}
@@ -1392,7 +1315,7 @@
private void handleVerifyUnlock() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
- mKeyguardViewManager.verifyUnlock();
+ mStatusBarKeyguardViewManager.verifyUnlock();
mShowing = true;
updateActivityLockScreenState();
}
@@ -1405,18 +1328,18 @@
private void handleNotifyScreenOff() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
- mKeyguardViewManager.onScreenTurnedOff();
+ mStatusBarKeyguardViewManager.onScreenTurnedOff();
}
}
/**
- * Handle message sent by {@link #notifyScreenOnLocked()}
+ * Handle message sent by {@link #notifyScreenOnLocked}
* @see #NOTIFY_SCREEN_ON
*/
private void handleNotifyScreenOn(IKeyguardShowCallback callback) {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
- mKeyguardViewManager.onScreenTurnedOn(callback);
+ mStatusBarKeyguardViewManager.onScreenTurnedOn(callback);
}
}
@@ -1424,35 +1347,23 @@
return mKeyguardDonePending || !isSecure();
}
- public void showAssistant() {
- Message msg = mHandler.obtainMessage(SHOW_ASSISTANT);
- mHandler.sendMessage(msg);
- }
-
- public void handleShowAssistant() {
- mKeyguardViewManager.showAssistant();
- }
-
private boolean isAssistantAvailable() {
return mSearchManager != null
&& mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
}
- public static MultiUserAvatarCache getAvatarCache() {
- return sMultiUserAvatarCache;
- }
-
- public void dispatch(MotionEvent event) {
- Message msg = mHandler.obtainMessage(DISPATCH_EVENT, event);
- mHandler.sendMessage(msg);
- }
-
- public void launchCamera() {
- Message msg = mHandler.obtainMessage(LAUNCH_CAMERA);
- mHandler.sendMessage(msg);
- }
-
public void onBootCompleted() {
mUpdateMonitor.dispatchBootCompleted();
}
+
+ public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,
+ ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+ mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
+ statusBarWindowManager);
+ return mStatusBarKeyguardViewManager;
+ }
+
+ public ViewMediatorCallback getViewMediatorCallback() {
+ return mViewMediatorCallback;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index cde17f5e..64770a4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -28,8 +28,9 @@
public static class App {
public static final boolean EnableTaskFiltering = true;
public static final boolean EnableTaskStackClipping = false;
- public static final boolean EnableToggleNewRecentsActivity = false;
- // This disables the bitmap and icon caches to
+ public static final boolean EnableInfoPane = true;
+
+ // This disables the bitmap and icon caches
public static final boolean DisableBackgroundCache = false;
// For debugging, this enables us to create mock recents tasks
public static final boolean EnableSystemServicesProxy = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f61c28c..71c45f2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -50,11 +50,7 @@
String action = intent.getAction();
Console.log(Constants.DebugFlags.App.SystemUIHandshake,
"[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
- if (action.equals(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY)) {
- if (Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
- finish();
- }
- } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
+ if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// Try and unfilter and filtered stacks
if (!mRecentsView.unfilterFilteredStacks()) {
// If there are no filtered stacks, dismiss recents and launch the first task
@@ -97,6 +93,12 @@
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
} else {
mEmptyView.setVisibility(View.GONE);
+
+ // Un-dim the background
+ WindowManager.LayoutParams wlp = getWindow().getAttributes();
+ wlp.dimAmount = 0f;
+ getWindow().setAttributes(wlp);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
}
@@ -190,7 +192,6 @@
// Register the broadcast receiver to handle messages from our service
IntentFilter filter = new IntentFilter();
filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
- filter.addAction(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY);
registerReceiver(mServiceBroadcastReceiver, filter);
// Register the broadcast receiver to handle messages when the screen is turned off
@@ -224,11 +225,6 @@
Console.AnsiRed);
super.onStop();
- // Finish the current recents activity after we have launched a task
- if (mTaskLaunched && Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
- finish();
- }
-
mVisible = false;
mTaskLaunched = false;
}
@@ -250,8 +246,18 @@
@Override
public void onBackPressed() {
- if (!mRecentsView.unfilterFilteredStacks()) {
- super.onBackPressed();
+ boolean interceptedByInfoPanelClose = false;
+
+ // Try and return from any open info panes
+ if (Constants.DebugFlags.App.EnableInfoPane) {
+ interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
+ }
+
+ // If we haven't been intercepted already, then unfilter any stacks
+ if (!interceptedByInfoPanelClose) {
+ if (!mRecentsView.unfilterFilteredStacks()) {
+ super.onBackPressed();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 8949663..5e5b841 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -40,6 +40,10 @@
public int filteringCurrentViewsMinAnimDuration;
public int filteringNewViewsMinAnimDuration;
public int taskBarEnterAnimDuration;
+ public int taskStackScrollDismissInfoPaneDistance;
+ public int taskStackMaxDim;
+ public int taskViewInfoPaneAnimDuration;
+ public int taskViewRoundedCornerRadiusPx;
public boolean launchedWithThumbnailAnimation;
@@ -81,6 +85,13 @@
res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
taskBarEnterAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
+ taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
+ R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
+ taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
+ taskViewInfoPaneAnimDuration =
+ res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
+ taskViewRoundedCornerRadiusPx =
+ res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
}
/** Updates the system insets */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index f78a999..06ca9e2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -112,7 +112,6 @@
/* Service */
public class RecentsService extends Service {
- final static String ACTION_FINISH_RECENTS_ACTIVITY = "action_finish_recents_activity";
final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index ec28379..b054a22 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -17,13 +17,16 @@
package com.android.systemui.recents.views;
import android.app.ActivityOptions;
+import android.app.TaskStackBuilder;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.net.Uri;
import android.os.UserHandle;
+import android.provider.Settings;
import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.recents.Console;
@@ -179,6 +182,21 @@
return true;
}
+ /** Closes any open info panes */
+ public boolean closeOpenInfoPanes() {
+ if (mBSP != null) {
+ // Get the first stack view
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskStackView stackView = (TaskStackView) getChildAt(i);
+ if (stackView.closeOpenInfoPanes()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/** Unfilters any filtered stacks */
public boolean unfilterFilteredStacks() {
if (mBSP != null) {
@@ -206,6 +224,9 @@
mCb.onTaskLaunching();
}
+ // Close any open info panes
+ closeOpenInfoPanes();
+
final Runnable launchRunnable = new Runnable() {
@Override
public void run() {
@@ -283,4 +304,15 @@
tv.animateOnLeavingRecents(launchRunnable);
}
}
+
+ @Override
+ public void onTaskAppInfoLaunched(Task t) {
+ // Create a new task stack with the application info details activity
+ Intent baseIntent = t.key.baseIntent;
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.fromParts("package", baseIntent.getComponent().getPackageName(), null));
+ intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
+ TaskStackBuilder.create(getContext())
+ .addNextIntentWithParentStack(intent).startActivities();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
new file mode 100644
index 0000000..233e38c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Utilities;
+
+
+/* The task info view */
+class TaskInfoView extends FrameLayout {
+
+ Button mAppInfoButton;
+
+ // Circular clip animation
+ boolean mCircularClipEnabled;
+ Path mClipPath = new Path();
+ float mClipRadius;
+ float mMaxClipRadius;
+ Point mClipOrigin = new Point();
+ ObjectAnimator mCircularClipAnimator;
+
+ public TaskInfoView(Context context) {
+ this(context, null);
+ }
+
+ public TaskInfoView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ // Initialize the buttons on the info panel
+ mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
+ }
+
+ /** Updates the positions of each of the items to fit in the rect specified */
+ void updateContents(Rect visibleRect) {
+ // Offset the app info button
+ LayoutParams lp = (LayoutParams) mAppInfoButton.getLayoutParams();
+ lp.topMargin = visibleRect.top +
+ (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2;
+ requestLayout();
+ }
+
+ /** Sets the circular clip radius on this panel */
+ public void setCircularClipRadius(float r) {
+ mClipRadius = r;
+ invalidate();
+ }
+
+ /** Gets the circular clip radius on this panel */
+ public float getCircularClipRadius() {
+ return mClipRadius;
+ }
+
+ /** Animates the circular clip radius on the icon */
+ void animateCircularClip(Point o, float fromRadius, float toRadius,
+ final Runnable postRunnable, boolean animateInContent) {
+ if (mCircularClipAnimator != null) {
+ mCircularClipAnimator.cancel();
+ }
+
+ // Calculate the max clip radius to each of the corners
+ int w = getMeasuredWidth() - o.x;
+ int h = getMeasuredHeight() - o.y;
+ // origin to tl, tr, br, bl
+ mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
+ mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
+ mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
+ mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
+
+ mClipOrigin.set(o.x, o.y);
+ mClipRadius = fromRadius;
+ int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
+ mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
+ mCircularClipAnimator.setDuration(duration);
+ mCircularClipAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCircularClipEnabled = false;
+ if (postRunnable != null) {
+ postRunnable.run();
+ }
+ }
+ });
+ mCircularClipAnimator.start();
+ mCircularClipEnabled = true;
+
+ if (animateInContent) {
+ animateAppInfoButtonIn(duration);
+ }
+ }
+
+ /** Cancels the circular clip animation. */
+ void cancelCircularClipAnimation() {
+ if (mCircularClipAnimator != null) {
+ mCircularClipAnimator.cancel();
+ }
+ }
+
+ void animateAppInfoButtonIn(int duration) {
+ mAppInfoButton.setScaleX(0.75f);
+ mAppInfoButton.setScaleY(0.75f);
+ mAppInfoButton.animate()
+ .scaleX(1f)
+ .scaleY(1f)
+ .setDuration(duration)
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .withLayer()
+ .start();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ int saveCount = 0;
+ if (mCircularClipEnabled) {
+ saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+ mClipPath.reset();
+ mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
+ Path.Direction.CW);
+ canvas.clipPath(mClipPath);
+ }
+ super.draw(canvas);
+ if (mCircularClipEnabled) {
+ canvas.restoreToCount(saveCount);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 88fb972..ee92b16 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -52,11 +52,12 @@
/* The visual representation of a task stack view */
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
- View.OnClickListener {
+ View.OnClickListener, View.OnLongClickListener {
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
+ public void onTaskAppInfoLaunched(Task t);
}
TaskStack mStack;
@@ -75,6 +76,7 @@
int mMinScroll;
int mMaxScroll;
int mStashedScroll;
+ int mLastInfoPaneStackScroll;
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
@@ -281,6 +283,17 @@
public void setStackScroll(int value) {
mStackScroll = value;
requestSynchronizeStackViewsWithModel();
+
+ // Close any open info panes if the user has scrolled away from them
+ boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
+ if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
+ config.taskStackScrollDismissInfoPaneDistance) {
+ // Close any open info panes
+ closeOpenInfoPanes();
+ }
+ }
}
/** Sets the current stack scroll without synchronizing the stack view with the model */
public void setStackScrollRaw(int value) {
@@ -300,19 +313,24 @@
// Enable hw layers on the stack
addHwLayersRefCount("animateBoundScroll");
- // Abort any current animations
- abortScroller();
- abortBoundScrollAnimation();
-
// Start a new scroll animation
- animateScroll(curScroll, newScroll);
- mScrollAnimator.start();
+ animateScroll(curScroll, newScroll, new Runnable() {
+ @Override
+ public void run() {
+ // Disable hw layers on the stack
+ decHwLayersRefCount("animateBoundScroll");
+ }
+ });
}
return mScrollAnimator;
}
/** Animates the stack scroll */
- void animateScroll(int curScroll, int newScroll) {
+ void animateScroll(int curScroll, int newScroll, final Runnable postRunnable) {
+ // Abort any current animations
+ abortScroller();
+ abortBoundScrollAnimation();
+
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
curScroll, 250));
@@ -326,20 +344,23 @@
mScrollAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- // Disable hw layers on the stack
- decHwLayersRefCount("animateBoundScroll");
+ if (postRunnable != null) {
+ postRunnable.run();
+ }
+ mScrollAnimator.removeAllListeners();
}
});
+ mScrollAnimator.start();
}
/** Aborts any current stack scrolls */
void abortBoundScrollAnimation() {
if (mScrollAnimator != null) {
mScrollAnimator.cancel();
- mScrollAnimator.removeAllListeners();
}
}
+ /** Aborts the scroller and any current fling */
void abortScroller() {
if (!mScroller.isFinished()) {
// Abort the scroller
@@ -407,6 +428,21 @@
}
}
+ /** Closes any open info panes. */
+ boolean closeOpenInfoPanes() {
+ if (!Constants.DebugFlags.App.EnableInfoPane) return false;
+
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ if (tv.isInfoPaneVisible()) {
+ tv.hideInfoPane();
+ return true;
+ }
+ }
+ return false;
+ }
+
/** Enables the hw layers and increments the hw layer requirement ref count */
void addHwLayersRefCount(String reason) {
Console.log(Constants.DebugFlags.UI.HwLayers,
@@ -528,8 +564,9 @@
int minHeight = (int) (mStackRect.height() -
(Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
- mTaskRect.set(mStackRect.left, mStackRectSansPeek.top,
- mStackRect.right, mStackRectSansPeek.top + size);
+ int left = mStackRect.left + (mStackRect.width() - size) / 2;
+ mTaskRect.set(left, mStackRectSansPeek.top,
+ left + size, mStackRectSansPeek.top + size);
// Update the scroll bounds
updateMinMaxScroll(false);
@@ -644,7 +681,6 @@
requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
}
-
/**
* Creates the animations for all the children views that need to be removed or to move views
* to their un/filtered position when we are un/filtering a stack, and returns the duration
@@ -789,6 +825,9 @@
@Override
public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
Task filteredTask) {
+ // Close any open info panes
+ closeOpenInfoPanes();
+
// Stash the scroll and filtered task for us to restore to when we unfilter
mStashedScroll = getStackScroll();
@@ -813,6 +852,9 @@
@Override
public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
+ // Close any open info panes
+ closeOpenInfoPanes();
+
// Calculate the current task transforms
final ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
@@ -892,6 +934,9 @@
// Set the callbacks and listeners for this new view
tv.setOnClickListener(this);
+ if (Constants.DebugFlags.App.EnableInfoPane) {
+ tv.setOnLongClickListener(this);
+ }
tv.setCallbacks(this);
} else {
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
@@ -926,6 +971,24 @@
}
}
+ @Override
+ public void onTaskInfoPanelShown(TaskView tv) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTaskInfoPanelHidden(TaskView tv) {
+ // Unset the saved scroll
+ mLastInfoPaneStackScroll = -1;
+ }
+
+ @Override
+ public void onTaskAppInfoClicked(TaskView tv) {
+ if (mCb != null) {
+ mCb.onTaskAppInfoLaunched(tv.getTask());
+ }
+ }
+
/**** View.OnClickListener Implementation ****/
@Override
@@ -935,10 +998,51 @@
Console.log(Constants.DebugFlags.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
task + " cb: " + mCb);
+ // Close any open info panes if the user taps on another task
+ if (closeOpenInfoPanes()) {
+ return;
+ }
+
if (mCb != null) {
mCb.onTaskLaunched(this, tv, mStack, task);
}
}
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (!Constants.DebugFlags.App.EnableInfoPane) return false;
+
+ TaskView tv = (TaskView) v;
+
+ // Close any other task info panels if we launch another info pane
+ closeOpenInfoPanes();
+
+ // Scroll the task view so that it is maximally visible
+ float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+ int taskIndex = mStack.indexOfTask(tv.getTask());
+ int curScroll = getStackScroll();
+ int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
+ TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
+ Rect nonOverlapRect = new Rect(transform.rect);
+ if (taskIndex < (mStack.getTaskCount() - 1)) {
+ nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
+ }
+
+ // XXX: Use HW Layers
+ if (transform.t < 0f) {
+ animateScroll(curScroll, newScroll, null);
+ } else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
+ // Check if we are out of bounds, if so, just scroll it in such that the bottom of the
+ // task view is visible
+ newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
+ animateScroll(curScroll, newScroll, null);
+ }
+ mLastInfoPaneStackScroll = newScroll;
+
+ // Show the info pane for this task view
+ tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
+ return true;
+ }
}
/* Handles touch events */
@@ -1153,9 +1257,10 @@
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int x = (int) ev.getX(activePointerIndex);
int y = (int) ev.getY(activePointerIndex);
+ int yTotal = Math.abs(y - mInitialMotionY);
int deltaY = mLastMotionY - y;
if (!mIsScrolling) {
- if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+ if (yTotal > mScrollTouchSlop) {
mIsScrolling = true;
// Initialize the velocity tracker
initOrResetVelocityTracker();
@@ -1277,6 +1382,13 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
+ // If the info panel is currently showing on this view, then we need to dismiss it
+ if (Constants.DebugFlags.App.EnableInfoPane) {
+ TaskView tv = (TaskView) v;
+ if (tv.isInfoPaneVisible()) {
+ tv.hideInfoPane();
+ }
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b4100127..d3b79d6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,31 +16,53 @@
package com.android.systemui.recents.views;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
/* A task view */
-public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
+public class TaskView extends FrameLayout implements View.OnClickListener,
+ Task.TaskCallbacks {
/** The TaskView callbacks */
interface TaskViewCallbacks {
public void onTaskIconClicked(TaskView tv);
+ public void onTaskInfoPanelShown(TaskView tv);
+ public void onTaskInfoPanelHidden(TaskView tv);
+ public void onTaskAppInfoClicked(TaskView tv);
+
// public void onTaskViewReboundToTask(TaskView tv, Task t);
}
+ int mDim;
+ int mMaxDim;
+ TimeInterpolator mDimInterpolator = new AccelerateInterpolator();
+
Task mTask;
boolean mTaskDataLoaded;
+ boolean mTaskInfoPaneVisible;
+ Point mLastTouchDown = new Point();
+ Path mRoundedRectClipPath = new Path();
TaskThumbnailView mThumbnailView;
TaskBarView mBarView;
+ TaskInfoView mInfoView;
TaskViewCallbacks mCb;
@@ -58,19 +80,47 @@
public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ setWillNotDraw(false);
}
@Override
protected void onFinishInflate() {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ mMaxDim = config.taskStackMaxDim;
+
// Bind the views
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
- mBarView.mApplicationIcon.setOnClickListener(this);
+ mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
+
if (mTaskDataLoaded) {
onTaskDataLoaded(false);
}
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ // Update the rounded rect clip path
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ float radius = config.taskViewRoundedCornerRadiusPx;
+ mRoundedRectClipPath.reset();
+ mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
+ radius, radius, Path.Direction.CW);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_MOVE:
+ mLastTouchDown.set((int) ev.getX(), (int) ev.getY());
+ break;
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+
/** Set callback */
void setCallbacks(TaskViewCallbacks cb) {
mCb = cb;
@@ -98,6 +148,12 @@
.setDuration(duration)
.setInterpolator(BakedBezierInterpolator.INSTANCE)
.withLayer()
+ .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateDimOverlayFromScale();
+ }
+ })
.start();
} else {
setTranslationY(toTransform.translationY);
@@ -105,6 +161,8 @@
setScaleY(toTransform.scale);
setAlpha(toTransform.alpha);
}
+ updateDimOverlayFromScale();
+ invalidate();
}
/** Resets this view's properties */
@@ -114,6 +172,7 @@
setScaleX(1f);
setScaleY(1f);
setAlpha(1f);
+ invalidate();
}
/**
@@ -189,6 +248,63 @@
return outRect;
}
+ /** Returns whether this task has an info pane visible */
+ boolean isInfoPaneVisible() {
+ return mTaskInfoPaneVisible;
+ }
+
+ /** Shows the info pane if it is not visible. */
+ void showInfoPane(Rect taskVisibleRect) {
+ if (mTaskInfoPaneVisible) return;
+
+ // Remove the bar view from the visible rect and update the info pane contents
+ taskVisibleRect.top += mBarView.getMeasuredHeight();
+ mInfoView.updateContents(taskVisibleRect);
+
+ // Show the info pane and animate it into view
+ mInfoView.setVisibility(View.VISIBLE);
+ mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
+ mInfoView.setOnClickListener(this);
+ mTaskInfoPaneVisible = true;
+
+ // Notify any callbacks
+ if (mCb != null) {
+ mCb.onTaskInfoPanelShown(this);
+ }
+ }
+
+ /** Hides the info pane if it is visible. */
+ void hideInfoPane() {
+ if (!mTaskInfoPaneVisible) return;
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+
+ // Cancel any circular clip animation
+ mInfoView.cancelCircularClipAnimation();
+
+ // Animate the info pane out
+ mInfoView.animate()
+ .alpha(0f)
+ .setDuration(config.taskViewInfoPaneAnimDuration)
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .withLayer()
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mInfoView.setVisibility(View.INVISIBLE);
+ mInfoView.setOnClickListener(null);
+
+ mInfoView.setAlpha(1f);
+ }
+ })
+ .start();
+ mTaskInfoPaneVisible = false;
+
+ // Notify any callbacks
+ if (mCb != null) {
+ mCb.onTaskInfoPanelHidden(this);
+ }
+ }
+
/** Enable the hw layers on this task view */
void enableHwLayers() {
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -199,6 +315,29 @@
mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
}
+ /** Update the dim as a function of the scale of this view. */
+ void updateDimOverlayFromScale() {
+ float minScale = Constants.Values.TaskStackView.StackPeekMinScale;
+ float scaleRange = 1f - minScale;
+ float dim = (1f - getScaleX()) / scaleRange;
+ dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
+ mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+ invalidate();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ // Apply the rounded rect clip path on the whole view
+ canvas.clipPath(mRoundedRectClipPath);
+
+ super.draw(canvas);
+
+ // Apply the dim if necessary
+ if (mDim > 0) {
+ canvas.drawColor(mDim << 24);
+ }
+ }
+
/**** TaskCallbacks Implementation ****/
/** Binds this task view to the task */
@@ -209,27 +348,39 @@
@Override
public void onTaskDataLoaded(boolean reloadingTaskData) {
- if (mThumbnailView != null && mBarView != null) {
+ if (mThumbnailView != null && mBarView != null && mInfoView != null) {
// Bind each of the views to the new task data
mThumbnailView.rebindToTask(mTask, reloadingTaskData);
mBarView.rebindToTask(mTask, reloadingTaskData);
+ // Rebind any listeners
+ mBarView.mApplicationIcon.setOnClickListener(this);
+ mInfoView.mAppInfoButton.setOnClickListener(this);
}
mTaskDataLoaded = true;
}
@Override
public void onTaskDataUnloaded() {
- if (mThumbnailView != null && mBarView != null) {
+ if (mThumbnailView != null && mBarView != null && mInfoView != null) {
// Unbind each of the views from the task data and remove the task callback
mTask.setCallbacks(null);
mThumbnailView.unbindFromTask();
mBarView.unbindFromTask();
+ // Unbind any listeners
+ mBarView.mApplicationIcon.setOnClickListener(null);
+ mInfoView.mAppInfoButton.setOnClickListener(null);
}
mTaskDataLoaded = false;
}
@Override
public void onClick(View v) {
- mCb.onTaskIconClicked(this);
+ if (v == mInfoView) {
+ // Do nothing
+ } else if (v == mBarView.mApplicationIcon) {
+ mCb.onTaskIconClicked(this);
+ } else if (v == mInfoView.mAppInfoButton) {
+ mCb.onTaskAppInfoClicked(this);
+ }
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
new file mode 100644
index 0000000..87ebcc1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.settings;
+
+import com.android.systemui.R;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+/**
+ * A quick and dirty view to show a user switcher.
+ */
+public class UserSwitcherHostView extends FrameLayout implements ListView.OnItemClickListener {
+
+ private static final String TAG = "UserSwitcherDialog";
+
+ private ArrayList<UserInfo> mUserInfo = new ArrayList<UserInfo>();
+ private Adapter mAdapter = new Adapter();
+ private UserManager mUserManager;
+ private Runnable mFinishRunnable;
+ private ListView mListView;
+
+ public UserSwitcherHostView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ if (isInEditMode()) {
+ return;
+ }
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ }
+
+ public UserSwitcherHostView(Context context, AttributeSet attrs) {
+ this(context, attrs, com.android.internal.R.attr.listViewStyle);
+ }
+
+ public UserSwitcherHostView(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mListView = (ListView) findViewById(android.R.id.list);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(this);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> l, View v, int position, long id) {
+ int userId = mAdapter.getItem(position).id;
+ try {
+ WindowManagerGlobal.getWindowManagerService().lockNow(null);
+ ActivityManagerNative.getDefault().switchUser(userId);
+ finish();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't switch user.", e);
+ }
+ }
+
+ private void finish() {
+ if (mFinishRunnable != null) {
+ mFinishRunnable.run();
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ finish();
+ }
+ return true;
+ }
+
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ // A gross hack to get rid of the switcher when the shade is collapsed.
+ if (visibility != VISIBLE) {
+ finish();
+ }
+ }
+
+ public void setFinishRunnable(Runnable finishRunnable) {
+ mFinishRunnable = finishRunnable;
+ }
+
+ public void refreshUsers() {
+ mUserInfo.clear();
+ mUserInfo.addAll(mUserManager.getUsers(true));
+ mAdapter.notifyDataSetChanged();
+ }
+
+ private class Adapter extends BaseAdapter {
+
+ @Override
+ public int getCount() {
+ return mUserInfo.size();
+ }
+
+ @Override
+ public UserInfo getItem(int position) {
+ return mUserInfo.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return getItem(position).serialNumber;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null || (!(convertView.getTag() instanceof ViewHolder))) {
+ convertView = createView(parent);
+ }
+ ViewHolder h = (ViewHolder) convertView.getTag();
+ bindView(h, getItem(position));
+ return convertView;
+ }
+
+ private View createView(ViewGroup parent) {
+ View v = LayoutInflater.from(getContext()).inflate(
+ R.layout.user_switcher_item, parent, false);
+ ViewHolder h = new ViewHolder();
+ h.name = (TextView) v.findViewById(R.id.user_name);
+ h.picture = (ImageView) v.findViewById(R.id.user_picture);
+ v.setTag(h);
+ return v;
+ }
+
+ private void bindView(ViewHolder h, UserInfo item) {
+ h.name.setText(item.name);
+ h.picture.setImageBitmap(mUserManager.getUserIcon(item.id));
+ }
+
+ class ViewHolder {
+ TextView name;
+ ImageView picture;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2f135ec..2ea5add 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -83,7 +83,7 @@
import java.util.Locale;
public abstract class BaseStatusBar extends SystemUI implements
- CommandQueue.Callbacks {
+ CommandQueue.Callbacks, LatestItemView.OnActivatedListener {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
@@ -168,9 +168,8 @@
protected int mZenMode;
- public IStatusBarService getStatusBarService() {
- return mBarService;
- }
+ protected boolean mOnKeyguard;
+ protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -423,9 +422,9 @@
}
- protected void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
- if (sbn.getNotification().contentView.getLayoutId() !=
- com.android.internal.R.layout.notification_template_base) {
+ protected void applyLegacyRowBackground(StatusBarNotification sbn,
+ NotificationData.Entry entry) {
+ if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
int version = 0;
try {
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
@@ -434,9 +433,11 @@
Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
}
if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
- content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
- } else {
- content.setBackgroundResource(com.android.internal.R.drawable.notification_bg);
+ entry.row.setBackgroundResource(R.drawable.notification_row_legacy_bg);
+ } else if (version < Build.VERSION_CODES.L) {
+ entry.row.setBackgroundResourceIds(
+ com.android.internal.R.drawable.notification_bg,
+ com.android.internal.R.drawable.notification_bg_dim);
}
}
}
@@ -871,8 +872,6 @@
row.setDrawingCacheEnabled(true);
- applyLegacyRowBackground(sbn, content);
-
if (MULTIUSER_DEBUG) {
TextView debug = (TextView) row.findViewById(R.id.debug_info);
if (debug != null) {
@@ -882,11 +881,14 @@
}
entry.row = row;
entry.row.setHeightRange(mRowMinHeight, mRowMaxHeight);
+ entry.row.setOnActivatedListener(this);
entry.content = content;
entry.expanded = contentViewLocal;
entry.expandedPublic = publicViewLocal;
entry.setBigContentView(bigContentViewLocal);
+ applyLegacyRowBackground(sbn, entry);
+
return true;
}
@@ -1004,7 +1006,7 @@
// Remove the expanded view.
ViewGroup rowParent = (ViewGroup)entry.row.getParent();
if (rowParent != null) rowParent.removeView(entry.row);
- updateExpansionStates();
+ updateRowStates();
updateNotificationIcons();
return entry.notification;
@@ -1047,7 +1049,7 @@
if (DEBUG) {
Log.d(TAG, "addNotificationViews: added at " + pos);
}
- updateExpansionStates();
+ updateRowStates();
updateNotificationIcons();
}
@@ -1055,28 +1057,89 @@
addNotificationViews(createNotificationViews(key, notification));
}
- protected void updateExpansionStates() {
+ /**
+ * @return The number of notifications we show on Keyguard.
+ */
+ protected abstract int getMaxKeyguardNotifications();
- // TODO: Handle user expansion better
- int N = mNotificationData.size();
- for (int i = 0; i < N; i++) {
+ /**
+ * Updates expanded, dimmed and locked states of notification rows.
+ */
+ protected void updateRowStates() {
+ int maxKeyguardNotifications = getMaxKeyguardNotifications();
+ mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
+ int n = mNotificationData.size();
+ int visibleNotifications = 0;
+ for (int i = n-1; i >= 0; i--) {
NotificationData.Entry entry = mNotificationData.get(i);
- if (!entry.row.isUserLocked()) {
- if (i == (N-1)) {
- if (DEBUG) Log.d(TAG, "expanding top notification at " + i);
- entry.row.setSystemExpanded(true);
- } else {
- if (!entry.row.isUserExpanded()) {
- if (DEBUG) Log.d(TAG, "collapsing notification at " + i);
- entry.row.setSystemExpanded(false);
- } else {
- if (DEBUG) Log.d(TAG, "ignoring user-modified notification at " + i);
- }
+ if (mOnKeyguard) {
+ entry.row.setSystemExpanded(false);
+ } else {
+ if (!entry.row.isUserLocked()) {
+ boolean top = (i == n-1);
+ entry.row.setSystemExpanded(top || entry.row.isUserExpanded());
+ }
+ }
+ entry.row.setDimmed(mOnKeyguard);
+ entry.row.setLocked(mOnKeyguard);
+ boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
+ if (mOnKeyguard && (visibleNotifications >= maxKeyguardNotifications
+ || !showOnKeyguard)) {
+ entry.row.setVisibility(View.GONE);
+ if (showOnKeyguard) {
+ mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
}
} else {
- if (DEBUG) Log.d(TAG, "ignoring notification being held by user at " + i);
+ entry.row.setVisibility(View.VISIBLE);
+ visibleNotifications++;
}
}
+
+ if (mOnKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
+ mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
+ } else {
+ mKeyguardIconOverflowContainer.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onActivated(View view) {
+ int n = mNotificationData.size();
+ for (int i = 0; i < n; i++) {
+ NotificationData.Entry entry = mNotificationData.get(i);
+ if (entry.row.getVisibility() != View.GONE) {
+ if (view == entry.row) {
+ entry.row.getActivator().activate();
+ } else {
+ entry.row.getActivator().activateInverse();
+ }
+ }
+ }
+ if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+ if (view == mKeyguardIconOverflowContainer) {
+ mKeyguardIconOverflowContainer.getActivator().activate();
+ } else {
+ mKeyguardIconOverflowContainer.getActivator().activateInverse();
+ }
+ }
+ }
+
+ @Override
+ public void onReset(View view) {
+ int n = mNotificationData.size();
+ for (int i = 0; i < n; i++) {
+ NotificationData.Entry entry = mNotificationData.get(i);
+ if (entry.row.getVisibility() != View.GONE) {
+ entry.row.getActivator().reset();
+ }
+ }
+ if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+ mKeyguardIconOverflowContainer.getActivator().reset();
+ }
+ }
+
+ private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+ return sbn.getNotification().priority >= Notification.PRIORITY_LOW;
}
protected void setZenMode(int mode) {
@@ -1208,7 +1271,7 @@
handleNotificationError(key, notification, "Couldn't update icon: " + ic);
return;
}
- updateExpansionStates();
+ updateRowStates();
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
@@ -1315,7 +1378,7 @@
boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
&& isAllowed
&& mPowerManager.isScreenOn()
- && !keyguard.isShowingAndNotHidden()
+ && !keyguard.isShowingAndNotOccluded()
&& !keyguard.isInputRestricted();
try {
interrupt = interrupt && !mDreamManager.isDreaming();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 39333d7..bbbe8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,6 +21,7 @@
import android.os.Message;
import android.service.notification.StatusBarNotification;
+import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
@@ -98,6 +99,7 @@
public void hideSearchPanel();
public void cancelPreloadRecentApps();
public void setWindowState(int window, int state);
+
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -232,6 +234,7 @@
}
}
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -295,7 +298,7 @@
mCallbacks.topAppWindowChanged(msg.arg1 != 0);
break;
case MSG_SHOW_IME_BUTTON:
- mCallbacks.setImeWindowStatus((IBinder)msg.obj, msg.arg1, msg.arg2);
+ mCallbacks.setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2);
break;
case MSG_SET_HARD_KEYBOARD_STATUS:
mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
@@ -312,6 +315,7 @@
case MSG_SET_WINDOW_STATE:
mCallbacks.setWindowState(msg.arg1, msg.arg2);
break;
+
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 2daf619..fdf4dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -25,7 +25,8 @@
import com.android.internal.widget.SizeAdaptiveLayout;
import com.android.systemui.R;
-public class ExpandableNotificationRow extends FrameLayout {
+public class ExpandableNotificationRow extends FrameLayout
+ implements LatestItemView.OnActivatedListener {
private int mRowMinHeight;
private int mRowMaxHeight;
@@ -40,6 +41,8 @@
/** Are we showing the "public" version */
private boolean mShowingPublic;
+ private LatestItemView mLatestItemView;
+
/**
* Is this notification expanded by the system. The expansion state can be overridden by the
* user expansion.
@@ -49,6 +52,8 @@
private SizeAdaptiveLayout mPrivateLayout;
private int mMaxExpandHeight;
private boolean mMaxHeightNeedsUpdate;
+ private NotificationActivator mActivator;
+ private LatestItemView.OnActivatedListener mOnActivatedListener;
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -59,6 +64,10 @@
super.onFinishInflate();
mPublicLayout = (SizeAdaptiveLayout) findViewById(R.id.expandedPublic);
mPrivateLayout = (SizeAdaptiveLayout) findViewById(R.id.expanded);
+ mLatestItemView = (LatestItemView) findViewById(R.id.container);
+
+ mActivator = new NotificationActivator(this);
+ mLatestItemView.setOnActivatedListener(this);
}
public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
@@ -152,8 +161,6 @@
return mShowingPublic ? mRowMinHeight : getMaxExpandHeight();
}
-
-
private void updateMaxExpandHeight() {
ViewGroup.LayoutParams lp = getLayoutParams();
int oldHeight = lp.height;
@@ -195,6 +202,14 @@
mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
}
+ /**
+ * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+ */
+ public void setDimmed(boolean dimmed) {
+ mLatestItemView.setDimmed(dimmed);
+ mActivator.setDimmed(dimmed);
+ }
+
public int getMaxExpandHeight() {
if (mMaxHeightNeedsUpdate) {
updateMaxExpandHeight();
@@ -202,4 +217,44 @@
}
return mMaxExpandHeight;
}
+
+ /**
+ * Sets the notification as locked. In the locked state, the first tap will produce a quantum
+ * ripple to make the notification brighter and only the second tap will cause a click.
+ */
+ public void setLocked(boolean locked) {
+ mLatestItemView.setLocked(locked);
+ }
+
+ public void setOnActivatedListener(LatestItemView.OnActivatedListener listener) {
+ mOnActivatedListener = listener;
+ }
+
+ public NotificationActivator getActivator() {
+ return mActivator;
+ }
+
+ @Override
+ public void onActivated(View view) {
+ if (mOnActivatedListener != null) {
+ mOnActivatedListener.onActivated(this);
+ }
+ }
+
+ @Override
+ public void onReset(View view) {
+ if (mOnActivatedListener != null) {
+ mOnActivatedListener.onReset(this);
+ }
+ }
+
+ /**
+ * Sets the resource id for the background of this notification.
+ *
+ * @param bgResId The background resource to use in normal state.
+ * @param dimmedBgResId The background resource to use in dimmed state.
+ */
+ public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+ mLatestItemView.setBackgroundResourceIds(bgResId, dimmedBgResId);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
index 6419777..5e90084 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
@@ -18,15 +18,48 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+import com.android.internal.R;
+
public class LatestItemView extends FrameLayout {
+
+ private static final long DOUBLETAP_TIMEOUT_MS = 1000;
+
+ private boolean mDimmed;
+ private boolean mLocked;
+
+ private int mBgResId = R.drawable.notification_quantum_bg;
+ private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim;
+
+ /**
+ * Flag to indicate that the notification has been touched once and the second touch will
+ * click it.
+ */
+ private boolean mActivated;
+
+ private float mDownX;
+ private float mDownY;
+ private final float mTouchSlop;
+
+ private OnActivatedListener mOnActivatedListener;
+
public LatestItemView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
+ private final Runnable mTapTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ makeInactive();
+ }
+ };
+
@Override
public void setOnClickListener(OnClickListener l) {
super.setOnClickListener(l);
@@ -45,4 +78,125 @@
}
return false;
}
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mLocked) {
+ return handleTouchEventLocked(event);
+ } else {
+ return super.onTouchEvent(event);
+ }
+ }
+
+ private boolean handleTouchEventLocked(MotionEvent event) {
+ int action = event.getActionMasked();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = event.getX();
+ mDownY = event.getY();
+
+ // Call the listener tentatively directly, even if we don't know whether the user
+ // will stay within the touch slop, as the listener is implemented as a scale
+ // animation, which is cancellable without jarring effects when swiping away
+ // notifications.
+ if (mOnActivatedListener != null) {
+ mOnActivatedListener.onActivated(this);
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!isWithinTouchSlop(event)) {
+ makeInactive();
+ return false;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (isWithinTouchSlop(event)) {
+ if (!mActivated) {
+ makeActive(event.getX(), event.getY());
+ postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
+ } else {
+ performClick();
+ makeInactive();
+ }
+ } else {
+ makeInactive();
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ makeInactive();
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ private void makeActive(float x, float y) {
+ getBackground().setHotspot(0, x, y);
+ mActivated = true;
+ }
+
+ /**
+ * Cancels the hotspot and makes the notification inactive.
+ */
+ private void makeInactive() {
+ if (mActivated) {
+ // Make sure that we clear the hotspot from the center.
+ getBackground().setHotspot(0, getWidth() / 2, getHeight() / 2);
+ getBackground().removeHotspot(0);
+ mActivated = false;
+ }
+ if (mOnActivatedListener != null) {
+ mOnActivatedListener.onReset(this);
+ }
+ removeCallbacks(mTapTimeoutRunnable);
+ }
+
+ private boolean isWithinTouchSlop(MotionEvent event) {
+ return Math.abs(event.getX() - mDownX) < mTouchSlop
+ && Math.abs(event.getY() - mDownY) < mTouchSlop;
+ }
+
+ /**
+ * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+ */
+ public void setDimmed(boolean dimmed) {
+ if (mDimmed != dimmed) {
+ mDimmed = dimmed;
+ updateBackgroundResource();
+ }
+ }
+
+ /**
+ * Sets the notification as locked. In the locked state, the first tap will produce a quantum
+ * ripple to make the notification brighter and only the second tap will cause a click.
+ */
+ public void setLocked(boolean locked) {
+ mLocked = locked;
+ }
+
+ /**
+ * Sets the resource id for the background of this notification.
+ *
+ * @param bgResId The background resource to use in normal state.
+ * @param dimmedBgResId The background resource to use in dimmed state.
+ */
+ public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+ mBgResId = bgResId;
+ mDimmedBgResId = dimmedBgResId;
+ updateBackgroundResource();
+ }
+
+ private void updateBackgroundResource() {
+ setBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
+ }
+
+ public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
+ mOnActivatedListener = onActivatedListener;
+ }
+
+ public interface OnActivatedListener {
+ void onActivated(View view);
+ void onReset(View view);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
new file mode 100644
index 0000000..620e457
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.R;
+
+/**
+ * A helper class used by both {@link com.android.systemui.statusbar.ExpandableNotificationRow} and
+ * {@link com.android.systemui.statusbar.NotificationOverflowIconsView} to make a notification look
+ * active after tapping it once on the Keyguard.
+ */
+public class NotificationActivator {
+
+ private static final int ANIMATION_LENGTH_MS = 220;
+ private static final float INVERSE_ALPHA = 0.9f;
+ private static final float DIMMED_SCALE = 0.95f;
+
+ private final View mTargetView;
+
+ private final Interpolator mFastOutSlowInInterpolator;
+ private final Interpolator mLinearOutSlowInInterpolator;
+ private final int mTranslationZ;
+
+ public NotificationActivator(View targetView) {
+ mTargetView = targetView;
+ Context ctx = targetView.getContext();
+ mFastOutSlowInInterpolator =
+ AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in);
+ mLinearOutSlowInInterpolator =
+ AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in);
+ mTranslationZ =
+ ctx.getResources().getDimensionPixelSize(R.dimen.z_distance_between_notifications);
+ mTargetView.animate().setDuration(ANIMATION_LENGTH_MS);
+ }
+
+ public void activateInverse() {
+ mTargetView.animate().withLayer().alpha(INVERSE_ALPHA);
+ }
+
+ public void activate() {
+ mTargetView.animate()
+ .setInterpolator(mLinearOutSlowInInterpolator)
+ .scaleX(1)
+ .scaleY(1)
+ .translationZBy(mTranslationZ);
+ }
+
+ public void reset() {
+ mTargetView.animate()
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .scaleX(DIMMED_SCALE)
+ .scaleY(DIMMED_SCALE)
+ .translationZBy(-mTranslationZ);
+ if (mTargetView.getAlpha() != 1.0f) {
+ mTargetView.animate().withLayer().alpha(1);
+ }
+ }
+
+ public void setDimmed(boolean dimmed) {
+ if (dimmed) {
+ mTargetView.setScaleX(DIMMED_SCALE);
+ mTargetView.setScaleY(DIMMED_SCALE);
+ } else {
+ mTargetView.setScaleX(1);
+ mTargetView.setScaleY(1);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
new file mode 100644
index 0000000..be58dad
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * Container view for overflowing notification icons on Keyguard.
+ */
+public class NotificationOverflowContainer extends FrameLayout
+ implements LatestItemView.OnActivatedListener {
+
+ private NotificationOverflowIconsView mIconsView;
+ private LatestItemView.OnActivatedListener mOnActivatedListener;
+ private NotificationActivator mActivator;
+
+ public NotificationOverflowContainer(Context context) {
+ super(context);
+ }
+
+ public NotificationOverflowContainer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NotificationOverflowContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public NotificationOverflowContainer(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
+ mIconsView.setMoreText((TextView) findViewById(R.id.more_text));
+
+ LatestItemView latestItemView = (LatestItemView) findViewById(R.id.container);
+ mActivator = new NotificationActivator(this);
+ mActivator.setDimmed(true);
+ latestItemView.setOnActivatedListener(this);
+ latestItemView.setLocked(true);
+ }
+
+ public NotificationOverflowIconsView getIconsView() {
+ return mIconsView;
+ }
+
+ public void setOnActivatedListener(LatestItemView.OnActivatedListener onActivatedListener) {
+ mOnActivatedListener = onActivatedListener;
+ }
+
+ @Override
+ public void onActivated(View view) {
+ if (mOnActivatedListener != null) {
+ mOnActivatedListener.onActivated(this);
+ }
+ }
+
+ @Override
+ public void onReset(View view) {
+ if (mOnActivatedListener != null) {
+ mOnActivatedListener.onReset(this);
+ }
+ }
+
+ public NotificationActivator getActivator() {
+ return mActivator;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
new file mode 100644
index 0000000..ce31894
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.IconMerger;
+
+/**
+ * A view to display all the overflowing icons on Keyguard.
+ */
+public class NotificationOverflowIconsView extends IconMerger {
+
+ private TextView mMoreText;
+ private int mTintColor;
+
+ public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
+ }
+
+ public void setMoreText(TextView moreText) {
+ mMoreText = moreText;
+ }
+
+ public void addNotification(NotificationData.Entry notification) {
+ StatusBarIconView v = new StatusBarIconView(getContext(), "",
+ notification.notification.getNotification());
+ v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ v.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
+ addView(v);
+ v.set(notification.icon.getStatusBarIcon());
+ updateMoreText();
+ }
+
+ private void updateMoreText() {
+ mMoreText.setText(getResources().getQuantityString(
+ R.plurals.keyguard_more_overflow_text, getChildCount(), getChildCount()));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
new file mode 100644
index 0000000..7cbde36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardViewBase;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * A class which manages the bouncer on the lockscreen.
+ */
+public class KeyguardBouncer {
+
+ private Context mContext;
+ private ViewMediatorCallback mCallback;
+ private LockPatternUtils mLockPatternUtils;
+ private ViewGroup mContainer;
+ private StatusBarWindowManager mWindowManager;
+ private KeyguardViewBase mKeyguardView;
+ private ViewGroup mRoot;
+
+ public KeyguardBouncer(Context context, ViewMediatorCallback callback,
+ LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
+ ViewGroup container) {
+ mContext = context;
+ mCallback = callback;
+ mLockPatternUtils = lockPatternUtils;
+ mContainer = container;
+ mWindowManager = windowManager;
+ }
+
+ public void prepare() {
+ ensureView();
+ }
+
+ public void show() {
+ ensureView();
+
+ // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
+ // Keyguard. If we need to authenticate, show the bouncer.
+ if (!mKeyguardView.dismiss()) {
+ mRoot.setVisibility(View.VISIBLE);
+ mKeyguardView.requestFocus();
+ }
+ }
+
+ public void hide() {
+ if (mKeyguardView != null) {
+ mKeyguardView.cleanUp();
+ }
+ removeView();
+ }
+
+ /**
+ * Reset the state of the view.
+ */
+ public void reset() {
+ inflateView();
+ }
+
+ public void onScreenTurnedOff() {
+ if (mKeyguardView != null) {
+ mKeyguardView.onScreenTurnedOff();
+ }
+ }
+
+ public void onScreenTurnedOn() {
+ if (mKeyguardView != null) {
+ mKeyguardView.onScreenTurnedOn();
+ }
+ }
+
+ public long getUserActivityTimeout() {
+ if (mKeyguardView != null) {
+ long timeout = mKeyguardView.getUserActivityTimeout();
+ if (timeout >= 0) {
+ return timeout;
+ }
+ }
+ return KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
+ }
+
+ public boolean isShowing() {
+ return mRoot != null && mRoot.getVisibility() == View.VISIBLE;
+ }
+
+ private void ensureView() {
+ if (mRoot == null) {
+ inflateView();
+ }
+ }
+
+ private void inflateView() {
+ removeView();
+ mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
+ mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);
+ mKeyguardView.setLockPatternUtils(mLockPatternUtils);
+ mKeyguardView.setViewMediatorCallback(mCallback);
+ mContainer.addView(mRoot, mContainer.getChildCount());
+ mRoot.setVisibility(View.INVISIBLE);
+ mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
+ }
+
+ private void removeView() {
+ if (mRoot != null && mRoot.getParent() == mContainer) {
+ mContainer.removeView(mRoot);
+ mRoot = null;
+ }
+ }
+
+ public boolean onBackPressed() {
+ return mKeyguardView != null && mKeyguardView.handleBackKey();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
index 1ea920d..754075a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
@@ -39,8 +39,8 @@
*/
public class KeyguardTouchDelegate {
// TODO: propagate changes to these to {@link KeyguardServiceDelegate}
- static final String KEYGUARD_PACKAGE = "com.android.keyguard";
- static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+ static final String KEYGUARD_PACKAGE = "com.android.systemui";
+ static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
private static KeyguardTouchDelegate sInstance;
private static final List<OnKeyguardConnectionListener> sConnectionListeners =
@@ -140,16 +140,16 @@
return false;
}
- public boolean isShowingAndNotHidden() {
+ public boolean isShowingAndNotOccluded() {
final IKeyguardService service = mService;
if (service != null) {
try {
- return service.isShowingAndNotHidden();
+ return service.isShowingAndNotOccluded();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
} else {
- Slog.w(TAG, "isShowingAndNotHidden(): NO SERVICE!");
+ Slog.w(TAG, "isShowingAndNotOccluded(): NO SERVICE!");
}
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index a74230b..d26b32f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -117,7 +117,7 @@
@Override
public void setContentVisible(boolean visible) {
final float alpha = visible ? 1 : 0;
- fadeContent(mView.getCameraButton(), alpha);
+ fadeContent(mView.getBackButton(), alpha);
fadeContent(mView.getSearchLight(), alpha);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d9e0903..db26a42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -34,17 +34,23 @@
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -92,12 +98,16 @@
final static boolean WORKAROUND_INVALID_LAYOUT = true;
final static int MSG_CHECK_INVALID_LAYOUT = 8686;
+ private final float mCameraDragDistance;
+
// used to disable the camera icon in navbar when disabled by DPM
private boolean mCameraDisabledByDpm;
// performs manual animation in sync with layout transitions
private final NavTransitionListener mTransitionListener = new NavTransitionListener();
+ private final PowerManager mPowerManager;
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -155,22 +165,73 @@
}
};
+ private final int mScaledTouchSlop;
+
private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
+ private float mStartX;
+ private boolean mTouchSlopReached;
+ private boolean mSkipCancelAnimation;
+
@Override
- public boolean onTouch(View cameraButtonView, MotionEvent event) {
+ public boolean onTouch(final View cameraButtonView, MotionEvent event) {
+ float realX = event.getRawX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// disable search gesture while interacting with camera
mDelegateHelper.setDisabled(true);
mBarTransitions.setContentVisible(false);
+ mStartX = realX;
+ mTouchSlopReached = false;
+ mSkipCancelAnimation = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (realX > mStartX) {
+ realX = mStartX;
+ }
+ if (realX < mStartX - mCameraDragDistance) {
+ ((KeyButtonView) cameraButtonView).setPressed(true);
+ mPowerManager.userActivity(event.getEventTime(), false);
+ } else {
+ ((KeyButtonView) cameraButtonView).setPressed(false);
+ }
+ if (realX < mStartX - mScaledTouchSlop) {
+ mTouchSlopReached = true;
+ }
+ cameraButtonView.setTranslationX(Math.max(realX - mStartX,
+ -mCameraDragDistance));
break;
case MotionEvent.ACTION_UP:
+ if (realX < mStartX - mCameraDragDistance) {
+ mContext.startActivityAsUser(
+ new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE),
+ UserHandle.CURRENT);
+ }
+ if (realX < mStartX - mScaledTouchSlop) {
+ mTouchSlopReached = true;
+ }
+ if (!mTouchSlopReached) {
+ mSkipCancelAnimation = true;
+ cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
+ setInterpolator(new DecelerateInterpolator()).withEndAction(
+ new Runnable() {
+ @Override
+ public void run() {
+ cameraButtonView.animate().translationX(0).
+ setInterpolator(new AccelerateInterpolator());
+ }
+ });
+ }
case MotionEvent.ACTION_CANCEL:
+ ((KeyButtonView) cameraButtonView).setPressed(false);
mDelegateHelper.setDisabled(false);
mBarTransitions.setContentVisible(true);
+ if (!mSkipCancelAnimation) {
+ cameraButtonView.animate().translationX(0)
+ .setInterpolator(new AccelerateInterpolator(2f));
+ }
break;
}
- return KeyguardTouchDelegate.getInstance(getContext()).dispatch(event);
+ return true;
}
};
@@ -235,6 +296,9 @@
KeyguardTouchDelegate.addListener(mKeyguardConnectionListener);
mCameraDisabledByDpm = isCameraDisabledByDpm();
watchForDevicePolicyChanges();
+ mCameraDragDistance = res.getDimension(R.dimen.camera_drag_distance);
+ mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
}
private void watchForDevicePolicyChanges() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index a3e35d1..324d6f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -151,7 +151,8 @@
if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
mPanelExpandedFractionSum = 0f;
for (PanelView pv : mPanels) {
- final boolean visible = pv.getVisibility() == View.VISIBLE;
+ boolean visible = pv.getExpandedHeight() > 0;
+ pv.setVisibility(visible ? View.VISIBLE : View.GONE);
// adjust any other panels that may be partially visible
if (pv.getExpandedHeight() > 0f) {
if (mState == STATE_CLOSED) {
@@ -166,11 +167,6 @@
if (thisFrac == 1f) fullyOpenedPanel = panel;
}
}
- if (pv.getExpandedHeight() > 0f) {
- if (!visible) pv.setVisibility(View.VISIBLE);
- } else {
- if (visible) pv.setVisibility(View.GONE);
- }
}
mPanelExpandedFractionSum /= mPanels.size();
if (fullyOpenedPanel != null && !mTracking) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 6922ca5..0266144c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -334,6 +334,7 @@
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener(mAnimationCallback);
+ setOnHierarchyChangeListener(mHierarchyListener);
}
private void loadDimens() {
@@ -630,11 +631,6 @@
return mViewName;
}
- @Override
- protected void onViewAdded(View child) {
- if (DEBUG) logf("onViewAdded: " + child);
- }
-
public View getHandle() {
return mHandleView;
}
@@ -651,6 +647,12 @@
int newHeight = getMeasuredHeight();
if (newHeight != mMaxPanelHeight) {
mMaxPanelHeight = newHeight;
+ // If the user isn't actively poking us, let's rubberband to the content
+ if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+ && mExpandedHeight > 0 && mExpandedHeight != mMaxPanelHeight
+ && mMaxPanelHeight > 0) {
+ mExpandedHeight = mMaxPanelHeight;
+ }
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
@@ -828,4 +830,15 @@
mTimeAnimator, ((mTimeAnimator!=null && mTimeAnimator.isStarted())?" (started)":"")
));
}
+
+ private final OnHierarchyChangeListener mHierarchyListener = new OnHierarchyChangeListener() {
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ if (DEBUG) logf("onViewAdded: " + child);
+ }
+
+ @Override
+ public void onChildViewRemoved(View parent, View child) {
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 841f3ca..e89544c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -16,14 +16,16 @@
package com.android.systemui.statusbar.phone;
+
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
+import static com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -61,11 +63,13 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -84,15 +88,20 @@
import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.InterceptedNotifications;
+import com.android.systemui.statusbar.LatestItemView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationOverflowContainer;
+import com.android.systemui.statusbar.NotificationOverflowIconsView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -103,10 +112,14 @@
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
static final String TAG = "PhoneStatusBar";
@@ -139,6 +152,9 @@
View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
private static final long AUTOHIDE_TIMEOUT_MS = 3000;
+ /** The minimum delay in ms between reports of notification visibility. */
+ private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
+
// fling gesture tuning parameters, scaled to display density
private float mSelfExpandVelocityPx; // classic value: 2000px/s
private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -174,6 +190,7 @@
StatusBarWindowView mStatusBarWindow;
PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
+ private StatusBarWindowManager mStatusBarWindowManager;
int mPixelFormat;
Object mQueueLock = new Object();
@@ -212,9 +229,12 @@
// top bar
View mNotificationPanelHeader;
+ View mKeyguardStatusView;
+ int mKeyguardMaxNotificationCount;
View mDateTimeView;
View mClearButton;
ImageView mSettingsButton, mNotificationButton;
+ View mKeyguardSettingsFlipButton;
// carrier/wifi label
private TextView mCarrierLabel;
@@ -337,6 +357,9 @@
private int mNavigationBarMode;
private Boolean mScreenOn;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private ViewMediatorCallback mKeyguardViewMediatorCallback;
+
private final Runnable mAutohide = new Runnable() {
@Override
public void run() {
@@ -349,10 +372,94 @@
private Runnable mOnFlipRunnable;
private InterceptedNotifications mIntercepted;
+ private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
+ new OnChildLocationsChangedListener() {
+ @Override
+ public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) {
+ userActivity();
+ }
+ };
+
public void setOnFlipRunnable(Runnable onFlipRunnable) {
mOnFlipRunnable = onFlipRunnable;
}
+ /** Keys of notifications currently visible to the user. */
+ private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>();
+ private long mLastVisibilityReportUptimeMs;
+
+ private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD
+ | ViewState.LOCATION_TOP_STACK_PEEKING
+ | ViewState.LOCATION_MAIN_AREA
+ | ViewState.LOCATION_BOTTOM_STACK_PEEKING;
+
+ private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
+ new OnChildLocationsChangedListener() {
+ @Override
+ public void onChildLocationsChanged(
+ NotificationStackScrollLayout stackScrollLayout) {
+ if (mHandler.hasCallbacks(mVisibilityReporter)) {
+ // Visibilities will be reported when the existing
+ // callback is executed.
+ return;
+ }
+ // Calculate when we're allowed to run the visibility
+ // reporter. Note that this timestamp might already have
+ // passed. That's OK, the callback will just be executed
+ // ASAP.
+ long nextReportUptimeMs =
+ mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS;
+ mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs);
+ }
+ };
+
+ // Tracks notifications currently visible in mNotificationStackScroller and
+ // emits visibility events via NoMan on changes.
+ private final Runnable mVisibilityReporter = new Runnable() {
+ private final ArrayList<String> mTmpNewlyVisibleNotifications = new ArrayList<String>();
+ private final ArrayList<String> mTmpCurrentlyVisibleNotifications = new ArrayList<String>();
+
+ @Override
+ public void run() {
+ mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
+
+ // 1. Loop over mNotificationData entries:
+ // A. Keep list of visible notifications.
+ // B. Keep list of previously hidden, now visible notifications.
+ // 2. Compute no-longer visible notifications by removing currently
+ // visible notifications from the set of previously visible
+ // notifications.
+ // 3. Report newly visible and no-longer visible notifications.
+ // 4. Keep currently visible notifications for next report.
+ int N = mNotificationData.size();
+ for (int i = 0; i < N; i++) {
+ Entry entry = mNotificationData.get(i);
+ String key = entry.notification.getKey();
+ boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key);
+ boolean currentlyVisible =
+ (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0;
+ if (currentlyVisible) {
+ // Build new set of visible notifications.
+ mTmpCurrentlyVisibleNotifications.add(key);
+ }
+ if (!previouslyVisible && currentlyVisible) {
+ mTmpNewlyVisibleNotifications.add(key);
+ }
+ }
+ ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications;
+ noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
+
+ logNotificationVisibilityChanges(
+ mTmpNewlyVisibleNotifications, noLongerVisibleNotifications);
+
+ mCurrentlyVisibleNotifications.clear();
+ mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
+
+ mTmpNewlyVisibleNotifications.clear();
+ mTmpCurrentlyVisibleNotifications.clear();
+ }
+ };
+
@Override
public void setZenMode(int mode) {
super.setZenMode(mode);
@@ -388,6 +495,7 @@
Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
mHeadsUpObserver);
}
+ startKeyguard();
}
// ================================================================================
@@ -494,10 +602,18 @@
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
+ mStackScroller.setChildLocationsChangedListener(mOnChildLocationsChangedListener);
+
+ mKeyguardIconOverflowContainer =
+ (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
+ R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
+ mKeyguardIconOverflowContainer.setOnActivatedListener(this);
+ mStackScroller.addView(mKeyguardIconOverflowContainer);
mExpandedContents = mStackScroller;
mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
+ mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
mClearButton.setOnClickListener(mClearButtonListener);
@@ -687,6 +803,13 @@
return mStatusBarView;
}
+ private void startKeyguard() {
+ KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
+ mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
+ mStatusBarWindow, mStatusBarWindowManager);
+ mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
+ }
+
@Override
protected void onShowSearchPanel() {
if (mNavigationBarView != null) {
@@ -764,10 +887,6 @@
}
}
- protected int getStatusBarGravity() {
- return Gravity.TOP | Gravity.FILL_HORIZONTAL;
- }
-
public int getStatusBarHeight() {
if (mNaturalBarHeight < 0) {
final Resources res = mContext.getResources();
@@ -1024,7 +1143,7 @@
}
if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0
- && !mNotificationPanel.isTracking()) {
+ && !mNotificationPanel.isTracking() && !mOnKeyguard) {
animateCollapsePanels();
}
}
@@ -1093,7 +1212,7 @@
ArrayList<View> toRemove = new ArrayList<View>();
for (int i=0; i< mStackScroller.getChildCount(); i++) {
View child = mStackScroller.getChildAt(i);
- if (!toShow.contains(child)) {
+ if (!toShow.contains(child) && child != mKeyguardIconOverflowContainer) {
toRemove.add(child);
}
}
@@ -1493,26 +1612,13 @@
// Expand the window to encompass the full screen in anticipation of the drag.
// This is only possible to do atomically because the status bar is at the top of the screen!
- WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
+ mStatusBarWindowManager.setStatusBarExpanded(true);
visibilityChanged(true);
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
}
- private void releaseFocus() {
- if (mStatusBarWindow == null) return;
- WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
- }
-
public void animateCollapsePanels() {
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
}
@@ -1524,9 +1630,6 @@
+ " flags=" + flags);
}
- // release focus immediately to kick off focus change transition
- releaseFocus();
-
if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
@@ -1538,6 +1641,10 @@
}
if (mStatusBarWindow != null) {
+
+ // release focus immediately to kick off focus change transition
+ mStatusBarWindowManager.setStatusBarFocusable(false);
+
mStatusBarWindow.cancelExpandHelper();
mStatusBarView.collapseAllPanels(true);
}
@@ -1796,11 +1903,7 @@
visibilityChanged(false);
// Shrink the window to the size of the status bar only
- WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
- lp.height = getStatusBarHeight();
- lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mWindowManager.updateViewLayout(mStatusBarWindow, lp);
+ mStatusBarWindowManager.setStatusBarExpanded(false);
if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1815,6 +1918,8 @@
}
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+
+ showBouncer();
}
public boolean interceptTouchEvent(MotionEvent event) {
@@ -2303,30 +2408,9 @@
}
private void addStatusBarWindow() {
- // Put up the view
- final int height = getStatusBarHeight();
-
- // Now that the status bar window encompasses the sliding panel and its
- // translucent backdrop, the entire thing is made TRANSLUCENT and is
- // hardware-accelerated.
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- height,
- WindowManager.LayoutParams.TYPE_STATUS_BAR,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
- PixelFormat.TRANSLUCENT);
-
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-
- lp.gravity = getStatusBarGravity();
- lp.setTitle("StatusBar");
- lp.packageName = mContext.getPackageName();
-
makeStatusBarView();
- mWindowManager.addView(mStatusBarWindow, lp);
+ mStatusBarWindowManager = new StatusBarWindowManager(mContext);
+ mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2464,8 +2548,6 @@
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenOn = false;
- // no waiting!
- makeExpandedInvisible();
notifyNavigationBarScreenOn(false);
notifyHeadsUpScreenOn(false);
finishBarAnimations();
@@ -2644,9 +2726,46 @@
mRowMinHeight = res.getDimensionPixelSize(R.dimen.notification_row_min_height);
mRowMaxHeight = res.getDimensionPixelSize(R.dimen.notification_row_max_height);
+ mKeyguardMaxNotificationCount = res.getInteger(R.integer.keyguard_max_notification_count);
+
if (false) Log.v(TAG, "updateResources");
}
+ // Visibility reporting
+
+ @Override
+ protected void visibilityChanged(boolean visible) {
+ if (visible) {
+ mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
+ } else {
+ // Report all notifications as invisible and turn down the
+ // reporter.
+ if (!mCurrentlyVisibleNotifications.isEmpty()) {
+ logNotificationVisibilityChanges(
+ Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
+ mCurrentlyVisibleNotifications.clear();
+ }
+ mHandler.removeCallbacks(mVisibilityReporter);
+ mStackScroller.setChildLocationsChangedListener(null);
+ }
+ super.visibilityChanged(visible);
+ }
+
+ private void logNotificationVisibilityChanges(
+ Collection<String> newlyVisible, Collection<String> noLongerVisible) {
+ if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
+ return;
+ }
+
+ String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]);
+ String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]);
+ try {
+ mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
+ } catch (RemoteException e) {
+ // Ignore.
+ }
+ }
+
//
// tracing
//
@@ -2815,4 +2934,126 @@
((DemoMode)v).dispatchDemoCommand(command, args);
}
}
+
+ public boolean isOnKeyguard() {
+ return mOnKeyguard;
+ }
+
+ public void showKeyguard() {
+ mOnKeyguard = true;
+ instantExpandNotificationsPanel();
+ if (isFlippedToSettings()) {
+ flipToNotifications();
+ }
+ mStatusBarWindow.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
+ mKeyguardStatusView.setVisibility(View.VISIBLE);
+ mNotificationPanelHeader.setVisibility(View.GONE);
+ if (mKeyguardSettingsFlipButton == null) {
+ ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
+ mKeyguardSettingsFlipButton = flipStub.inflate();
+ installSettingsButton(mKeyguardSettingsFlipButton);
+ }
+ mKeyguardSettingsFlipButton.setVisibility(View.VISIBLE);
+ mKeyguardSettingsFlipButton.findViewById(R.id.settings_button).setVisibility(View.VISIBLE);
+ mKeyguardSettingsFlipButton.findViewById(R.id.notification_button)
+ .setVisibility(View.INVISIBLE);
+ updateRowStates();
+ }
+
+ public void hideKeyguard() {
+ mOnKeyguard = false;
+ mStatusBarWindow.setSystemUiVisibility(0);
+ mKeyguardStatusView.setVisibility(View.GONE);
+ mNotificationPanelHeader.setVisibility(View.VISIBLE);
+ mKeyguardSettingsFlipButton.setVisibility(View.GONE);
+ updateRowStates();
+ }
+
+ public void userActivity() {
+ if (mOnKeyguard) {
+ mKeyguardViewMediatorCallback.userActivity();
+ }
+ }
+
+ public boolean onBackPressed() {
+ if (mOnKeyguard) {
+ return mStatusBarKeyguardViewManager.onBackPressed();
+ } else {
+ animateCollapsePanels();
+ return true;
+ }
+ }
+
+ private void showBouncer() {
+ if (mOnKeyguard) {
+ mStatusBarKeyguardViewManager.dismiss();
+ }
+ }
+
+ private void instantExpandNotificationsPanel() {
+ mExpandedVisible = true;
+ mNotificationPanel.setExpandedFraction(1);
+ }
+
+ @Override
+ public void onActivated(View view) {
+ userActivity();
+ super.onActivated(view);
+ }
+
+ @Override
+ protected int getMaxKeyguardNotifications() {
+ return mKeyguardMaxNotificationCount;
+ }
+
+ /**
+ * @return a ViewGroup that spans the entire panel which contains the quick settings
+ */
+ public ViewGroup getQuickSettingsOverlayParent() {
+ if (mHasSettingsPanel) {
+ if (mHasFlipSettings) {
+ return mNotificationPanel;
+ } else {
+ return mSettingsPanel;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ private void installSettingsButton(View parent) {
+ final ImageView settingsButton =
+ (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
+ final ImageView notificationButton =
+ (ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
+ if (settingsButton != null) {
+ settingsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ animateExpandSettingsPanel();
+ v.setVisibility(View.INVISIBLE);
+ notificationButton.setVisibility(View.VISIBLE);
+ }
+ });
+ settingsButton.setVisibility(View.VISIBLE);
+ if (mHasSettingsPanel) {
+ // the settings panel is hiding behind this button
+ settingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+ } else {
+ // no settings panel, go straight to settings
+ settingsButton.setImageResource(R.drawable.ic_notify_settings);
+ }
+ }
+ if (notificationButton != null) {
+ notificationButton.setVisibility(View.INVISIBLE);
+ notificationButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ flipToNotifications();
+ v.setVisibility(View.INVISIBLE);
+ settingsButton.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index d9e3fdf..583fc3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -37,6 +37,7 @@
PhoneStatusBar mBar;
int mScrimColor;
+ int mScrimColorKeyguard;
float mSettingsPanelDragzoneFrac;
float mSettingsPanelDragzoneMin;
@@ -52,6 +53,7 @@
Resources res = getContext().getResources();
mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
+ mScrimColorKeyguard = res.getColor(R.color.notification_panel_scrim_color_keyguard);
mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
try {
mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
@@ -217,6 +219,7 @@
if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()
&& mBar.mStatusBarWindow != null) {
if (mShouldFade) {
+ int scrimColor = mBar.isOnKeyguard() ? mScrimColorKeyguard : mScrimColor;
frac = mPanelExpandedFractionSum; // don't judge me
// let's start this 20% of the way down the screen
frac = frac * 1.2f - 0.2f;
@@ -226,7 +229,7 @@
// woo, special effects
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
// attenuate background color alpha by k
- final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+ final int color = (int) ((scrimColor >>> 24) * k) << 24 | (scrimColor & 0xFFFFFF);
mBar.mStatusBarWindow.setBackgroundColor(color);
}
}
@@ -249,5 +252,6 @@
mBar.animateHeadsUp(mNotificationPanel == panel, mPanelExpandedFractionSum);
mBar.updateCarrierLabelVisibility(false);
+ mBar.userActivity();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index d67f7cd..b3fba76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -71,6 +71,7 @@
import com.android.internal.app.MediaRouteDialogPresenter;
import com.android.systemui.R;
+import com.android.systemui.settings.UserSwitcherHostView;
import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
@@ -310,30 +311,28 @@
collapsePanels();
}
- private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
+ private void addUserTiles(final ViewGroup parent, final LayoutInflater inflater) {
QuickSettingsTileView userTile = (QuickSettingsTileView)
inflater.inflate(R.layout.quick_settings_tile, parent, false);
userTile.setContent(R.layout.quick_settings_tile_user, inflater);
userTile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- collapsePanels();
final UserManager um = UserManager.get(mContext);
if (um.isUserSwitcherEnabled()) {
- // Since keyguard and systemui were merged into the same process to save
- // memory, they share the same Looper and graphics context. As a result,
- // there's no way to allow concurrent animation while keyguard inflates.
- // The workaround is to add a slight delay to allow the animation to finish.
- mHandler.postDelayed(new Runnable() {
+ final ViewGroup switcherParent = getService().getQuickSettingsOverlayParent();
+ final UserSwitcherHostView switcher = (UserSwitcherHostView) inflater.inflate(
+ R.layout.user_switcher_host, switcherParent, false);
+ switcher.setFinishRunnable(new Runnable() {
+ @Override
public void run() {
- try {
- WindowManagerGlobal.getWindowManagerService().lockNow(null);
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't show user switcher", e);
- }
+ switcherParent.removeView(switcher);
}
- }, 400); // TODO: ideally this would be tied to the collapse of the panel
+ });
+ switcher.refreshUsers();
+ switcherParent.addView(switcher);
} else {
+ collapsePanels();
Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
mContext, v, ContactsContract.Profile.CONTENT_URI,
ContactsContract.QuickContact.MODE_LARGE, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
new file mode 100644
index 0000000..b8592c3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSimpleHostView;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
+ * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
+ * which is in turn, reported to this class by the current
+ * {@link com.android.keyguard.KeyguardViewBase}.
+ */
+public class StatusBarKeyguardViewManager {
+ private static String TAG = "StatusBarKeyguardViewManager";
+
+ private final Context mContext;
+
+ private LockPatternUtils mLockPatternUtils;
+ private ViewMediatorCallback mViewMediatorCallback;
+ private PhoneStatusBar mPhoneStatusBar;
+
+ private ViewGroup mContainer;
+ private StatusBarWindowManager mStatusBarWindowManager;
+
+ private boolean mScreenOn = false;
+ private KeyguardBouncer mBouncer;
+ private boolean mShowing;
+
+ public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
+ LockPatternUtils lockPatternUtils) {
+ mContext = context;
+ mViewMediatorCallback = callback;
+ mLockPatternUtils = lockPatternUtils;
+ }
+
+ public void registerStatusBar(PhoneStatusBar phoneStatusBar,
+ ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+ mPhoneStatusBar = phoneStatusBar;
+ mContainer = container;
+ mStatusBarWindowManager = statusBarWindowManager;
+ mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
+ mStatusBarWindowManager, container);
+ }
+
+ /**
+ * Show the keyguard. Will handle creating and attaching to the view manager
+ * lazily.
+ */
+ public void show(Bundle options) {
+ mShowing = true;
+ mStatusBarWindowManager.setKeyguardShowing(true);
+ mPhoneStatusBar.showKeyguard();
+ mBouncer.prepare();
+ updateBackButtonState();
+ }
+
+ public void showBouncer() {
+ mBouncer.show();
+ updateBackButtonState();
+ }
+
+ /**
+ * Reset the state of the view.
+ */
+ public void reset() {
+ mBouncer.reset();
+ mPhoneStatusBar.showKeyguard();
+ updateBackButtonState();
+ }
+
+ public void onScreenTurnedOff() {
+ mScreenOn = false;
+ mBouncer.onScreenTurnedOff();
+ }
+
+ public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
+ mScreenOn = true;
+ mBouncer.onScreenTurnedOn();
+ if (callback != null) {
+ callbackAfterDraw(callback);
+ }
+ }
+
+ private void callbackAfterDraw(final IKeyguardShowCallback callback) {
+ mContainer.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ callback.onShown(mContainer.getWindowToken());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception calling onShown():", e);
+ }
+ }
+ });
+ }
+
+ public void verifyUnlock() {
+ dismiss();
+ }
+
+ public void setNeedsInput(boolean needsInput) {
+ mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
+ }
+
+ public void updateUserActivityTimeout() {
+ mStatusBarWindowManager.setKeyguardUserActivityTimeout(mBouncer.getUserActivityTimeout());
+ }
+
+ public void setOccluded(boolean occluded) {
+ mStatusBarWindowManager.setKeyguardOccluded(occluded);
+ }
+
+ /**
+ * Hides the keyguard view
+ */
+ public void hide() {
+ mShowing = false;
+ mPhoneStatusBar.hideKeyguard();
+ mStatusBarWindowManager.setKeyguardShowing(false);
+ mBouncer.hide();
+ mViewMediatorCallback.keyguardGone();
+ }
+
+ /**
+ * Dismisses the keyguard by going to the next screen or making it gone.
+ */
+ public void dismiss() {
+ if (mScreenOn) {
+ showBouncer();
+ }
+ }
+
+ /**
+ * @return Whether the keyguard is showing
+ */
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ /**
+ * Notifies this manager that the back button has been pressed.
+ *
+ * @return whether the back press has been handled
+ */
+ public boolean onBackPressed() {
+ if (mBouncer.isShowing()) {
+ mBouncer.hide();
+ mPhoneStatusBar.showKeyguard();
+ updateBackButtonState();
+ return true;
+ }
+ return false;
+ }
+
+ private void updateBackButtonState() {
+ int vis = mContainer.getSystemUiVisibility();
+ if (mBouncer.isShowing()) {
+ mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
+ } else {
+ mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
new file mode 100644
index 0000000..6153cde
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.SystemProperties;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.keyguard.R;
+
+/**
+ * Encapsulates all logic for the status bar window state management.
+ */
+public class StatusBarWindowManager {
+
+ private final Context mContext;
+ private final WindowManager mWindowManager;
+ private View mStatusBarView;
+ private WindowManager.LayoutParams mLp;
+ private int mBarHeight;
+ private final boolean mKeyguardScreenRotation;
+
+ private final State mCurrentState = new State();
+
+ public StatusBarWindowManager(Context context) {
+ mContext = context;
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+ }
+
+ private boolean shouldEnableKeyguardScreenRotation() {
+ Resources res = mContext.getResources();
+ return SystemProperties.getBoolean("lockscreen.rot_override", false)
+ || res.getBoolean(R.bool.config_enableLockScreenRotation);
+ }
+
+ /**
+ * Adds the status bar view to the window manager.
+ *
+ * @param statusBarView The view to add.
+ * @param barHeight The height of the status bar in collapsed state.
+ */
+ public void add(View statusBarView, int barHeight) {
+
+ // Now that the status bar window encompasses the sliding panel and its
+ // translucent backdrop, the entire thing is made TRANSLUCENT and is
+ // hardware-accelerated.
+ mLp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ barHeight,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+ PixelFormat.TRANSLUCENT);
+
+ mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+ mLp.setTitle("StatusBar");
+ mLp.packageName = mContext.getPackageName();
+ mStatusBarView = statusBarView;
+ mBarHeight = barHeight;
+ mWindowManager.addView(mStatusBarView, mLp);
+ }
+
+ private void applyKeyguardFlags(State state) {
+ if (state.keyguardShowing) {
+ mLp.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ mLp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ } else {
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ mLp.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ }
+ }
+
+ private void adjustScreenOrientation(State state) {
+ if (!state.isKeyguardShowingAndNotOccluded() || mKeyguardScreenRotation) {
+ mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+ } else {
+ mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+ }
+ }
+
+ private void applyFocusableFlag(State state) {
+ if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput) {
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ } else {
+ mLp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ }
+ }
+
+ private void applyHeight(State state) {
+ boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded;
+ if (expanded) {
+ mLp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ } else {
+ mLp.height = mBarHeight;
+ }
+ }
+
+ private void applyUserActivityTimeout(State state) {
+ if (state.isKeyguardShowingAndNotOccluded()) {
+ mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
+ } else {
+ mLp.userActivityTimeout = -1;
+ }
+ }
+
+ private void applyInputFeatures(State state) {
+ if (state.isKeyguardShowingAndNotOccluded()) {
+ mLp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+ } else {
+ mLp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+ }
+ }
+
+ private void apply(State state) {
+ applyKeyguardFlags(state);
+ applyFocusableFlag(state);
+ adjustScreenOrientation(state);
+ applyHeight(state);
+ applyUserActivityTimeout(state);
+ applyInputFeatures(state);
+ mWindowManager.updateViewLayout(mStatusBarView, mLp);
+ }
+
+ public void setKeyguardShowing(boolean showing) {
+ mCurrentState.keyguardShowing = showing;
+ apply(mCurrentState);
+ }
+
+ public void setKeyguardOccluded(boolean occluded) {
+ mCurrentState.keyguardOccluded = occluded;
+ apply(mCurrentState);
+ }
+
+ public void setKeyguardNeedsInput(boolean needsInput) {
+ mCurrentState.keyguardNeedsInput = needsInput;
+ apply(mCurrentState);
+ }
+
+ public void setStatusBarExpanded(boolean expanded) {
+ mCurrentState.statusBarExpanded = expanded;
+ mCurrentState.statusBarFocusable = expanded;
+ apply(mCurrentState);
+ }
+
+ public void setStatusBarFocusable(boolean focusable) {
+ mCurrentState.statusBarFocusable = focusable;
+ apply(mCurrentState);
+ }
+
+ public void setKeyguardUserActivityTimeout(long timeout) {
+ mCurrentState.keyguardUserActivityTimeout = timeout;
+ apply(mCurrentState);
+ }
+
+ private static class State {
+ boolean keyguardShowing;
+ boolean keyguardOccluded;
+ boolean keyguardNeedsInput;
+ boolean statusBarExpanded;
+ boolean statusBarFocusable;
+ long keyguardUserActivityTimeout;
+
+ private boolean isKeyguardShowingAndNotOccluded() {
+ return keyguardShowing && !keyguardOccluded;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a7121c4..dd89f47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -79,7 +79,7 @@
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_BACK:
if (!down) {
- mService.animateCollapsePanels();
+ mService.onBackPressed();
}
return true;
}
@@ -90,7 +90,8 @@
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
if (mNotificationPanel.isFullyExpanded()
- && mStackScrollLayout.getVisibility() == View.VISIBLE) {
+ && mStackScrollLayout.getVisibility() == View.VISIBLE
+ && !mService.isOnKeyguard()) {
intercept = mExpandHelper.onInterceptTouchEvent(ev);
}
if (!intercept) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index f31896a..9800bc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -656,9 +656,11 @@
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- height += child.getHeight();
- if (i < getChildCount()-1) {
- height += mPaddingBetweenElements;
+ if (child.getVisibility() != View.GONE) {
+ height += child.getHeight();
+ if (i < getChildCount()-1) {
+ height += mPaddingBetweenElements;
+ }
}
}
mContentHeight = height;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 5506a55..431f6fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -23,6 +23,8 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
+import java.util.ArrayList;
+
/**
* The Algorithm of the {@link com.android.systemui.statusbar.stack
* .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
@@ -98,6 +100,7 @@
algorithmState.lastTopStackIndex = 0;
algorithmState.scrollY = resultState.getScrollY();
algorithmState.itemsInBottomStack = 0.0f;
+ updateVisibleChildren(resultState, algorithmState);
// Phase 1:
findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
@@ -113,6 +116,23 @@
}
/**
+ * Update the visible children on the state.
+ */
+ private void updateVisibleChildren(StackScrollState resultState,
+ StackScrollAlgorithmState state) {
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+ state.visibleChildren.clear();
+ state.visibleChildren.ensureCapacity(childCount);
+ for (int i = 0; i < childCount; i++) {
+ View v = hostView.getChildAt(i);
+ if (v.getVisibility() != View.GONE) {
+ state.visibleChildren.add(v);
+ }
+ }
+ }
+
+ /**
* Determine the positions for the views. This is the main part of the algorithm.
*
* @param resultState The result state to update if a change to the properties of a child occurs
@@ -135,11 +155,10 @@
// How far in is the element currently transitioning into the bottom stack.
float yPositionInScrollView = 0.0f;
- ViewGroup hostView = resultState.getHostView();
- int childCount = hostView.getChildCount();
+ int childCount = algorithmState.visibleChildren.size();
int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
+ View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
childViewState.yTranslation = currentYPosition;
childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
@@ -317,12 +336,11 @@
// The y Position if the element would be in a regular scrollView
float yPositionInScrollView = 0.0f;
- ViewGroup hostView = resultState.getHostView();
- int childCount = hostView.getChildCount();
+ int childCount = algorithmState.visibleChildren.size();
// find the number of elements in the top stack.
for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
+ View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
int childHeight = child.getHeight();
float yPositionInScrollViewAfterElement = yPositionInScrollView
@@ -397,10 +415,9 @@
*/
private void updateZValuesForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState) {
- ViewGroup hostView = resultState.getHostView();
- int childCount = hostView.getChildCount();
+ int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
+ View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
if (i < algorithmState.itemsInTopStack) {
float stackIndex = algorithmState.itemsInTopStack - i;
@@ -434,8 +451,8 @@
}
private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
- if (hostView.getChildCount() > 0) {
- mFirstChildWhileExpanding = hostView.getChildAt(0);
+ mFirstChildWhileExpanding = findFirstVisibleChild(hostView);
+ if (mFirstChildWhileExpanding != null) {
if (mExpandedOnStart) {
// We are collapsing the shade, so the first child can get as most as high as the
@@ -447,11 +464,21 @@
mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
}
} else {
- mFirstChildWhileExpanding = null;
mFirstChildMaxHeight = 0;
}
}
+ private View findFirstVisibleChild(ViewGroup container) {
+ int childCount = container.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = container.getChildAt(i);
+ if (child.getVisibility() != View.GONE) {
+ return child;
+ }
+ }
+ return null;
+ }
+
public void onExpansionStopped() {
mIsExpansionChanging = false;
mFirstChildWhileExpanding = null;
@@ -501,6 +528,11 @@
* how far in is the element currently transitioning into the bottom stack
*/
public float partialInBottom;
+
+ /**
+ * The children from the host view which are not gone.
+ */
+ public final ArrayList<View> visibleChildren = new ArrayList<View>();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 67a1735..06a08f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -63,7 +63,8 @@
}
// initialize with the default values of the view
viewState.height = child.getHeight();
- viewState.alpha = 1.0f;
+ viewState.alpha = 1;
+ viewState.gone = child.getVisibility() == View.GONE;
}
}
@@ -116,7 +117,7 @@
// apply visibility
int oldVisibility = child.getVisibility();
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
- if (newVisibility != oldVisibility) {
+ if (newVisibility != oldVisibility && !state.gone) {
child.setVisibility(newVisibility);
}
@@ -164,6 +165,7 @@
float yTranslation;
float zTranslation;
int height;
+ boolean gone;
/**
* The location this view is currently rendered at.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index dd13e31..d615542 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -22,6 +22,7 @@
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
+import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -93,10 +94,6 @@
}
@Override
- protected void createAndAddWindows() {
- }
-
- @Override
protected WindowManager.LayoutParams getSearchLayoutParams(
LayoutParams layoutParams) {
return null;
@@ -141,10 +138,19 @@
}
@Override
+ protected int getMaxKeyguardNotifications() {
+ return 0;
+ }
+
+ @Override
public void animateExpandSettingsPanel() {
}
@Override
+ protected void createAndAddWindows() {
+ }
+
+ @Override
protected void refreshLayout(int layoutDirection) {
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 216f6a4..77e2462 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -96,6 +96,8 @@
import android.view.animation.AnimationUtils;
import com.android.internal.R;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
import com.android.internal.statusbar.IStatusBarService;
@@ -174,6 +176,8 @@
* Keyguard stuff
*/
private WindowState mKeyguardScrim;
+ private boolean mKeyguardHidden;
+ private boolean mKeyguardDrawn;
/* Table of Application Launch keys. Maps from key codes to intent categories.
*
@@ -248,7 +252,6 @@
int[] mNavigationBarHeightForRotation = new int[4];
int[] mNavigationBarWidthForRotation = new int[4];
- WindowState mKeyguard = null;
KeyguardServiceDelegate mKeyguardDelegate;
GlobalActions mGlobalActions;
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
@@ -1311,7 +1314,6 @@
case TYPE_BOOT_PROGRESS:
case TYPE_DISPLAY_OVERLAY:
case TYPE_HIDDEN_NAV_CONSUMER:
- case TYPE_KEYGUARD:
case TYPE_KEYGUARD_SCRIM:
case TYPE_KEYGUARD_DIALOG:
case TYPE_MAGNIFICATION_OVERLAY:
@@ -1348,6 +1350,22 @@
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
break;
+ case TYPE_STATUS_BAR:
+
+ // If the Keyguard is in a hidden state (occluded by another window), we force to
+ // remove the wallpaper and keyguard flag so that any change in-flight after setting
+ // the keyguard as occluded wouldn't set these flags again.
+ // See {@link #processKeyguardSetHiddenResultLw}.
+ if (mKeyguardHidden) {
+ attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ }
+ break;
+ }
+
+ if (attrs.type != TYPE_STATUS_BAR) {
+ // The status bar is the only window allowed to exhibit keyguard behavior.
+ attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
}
@@ -1434,54 +1452,50 @@
case TYPE_KEYGUARD_SCRIM:
// the safety window that shows behind keyguard while keyguard is starting
return 12;
- case TYPE_KEYGUARD:
- // the keyguard; nothing on top of these can take focus, since they are
- // responsible for power management when displayed.
- return 13;
- case TYPE_KEYGUARD_DIALOG:
- return 14;
case TYPE_STATUS_BAR_SUB_PANEL:
- return 15;
+ return 13;
case TYPE_STATUS_BAR:
- return 16;
+ return 14;
case TYPE_STATUS_BAR_PANEL:
- return 17;
+ return 15;
+ case TYPE_KEYGUARD_DIALOG:
+ return 16;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 18;
+ return 17;
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 19;
+ return 18;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
- return 20;
+ return 19;
case TYPE_NAVIGATION_BAR_PANEL:
// some panels (e.g. search) need to show on top of the navigation bar
- return 21;
+ return 20;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
- return 22;
+ return 21;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
- return 23;
+ return 22;
case TYPE_DISPLAY_OVERLAY:
// used to simulate secondary display devices
- return 24;
+ return 23;
case TYPE_DRAG:
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- return 25;
+ return 24;
case TYPE_SECURE_SYSTEM_OVERLAY:
- return 26;
+ return 25;
case TYPE_BOOT_PROGRESS:
- return 27;
+ return 26;
case TYPE_POINTER:
// the (mouse) pointer layer
- return 28;
+ return 27;
case TYPE_HIDDEN_NAV_CONSUMER:
- return 29;
+ return 28;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
@@ -1551,7 +1565,7 @@
@Override
public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
- return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
+ return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
}
@Override
@@ -1562,7 +1576,6 @@
case TYPE_WALLPAPER:
case TYPE_DREAM:
case TYPE_UNIVERSE_BACKGROUND:
- case TYPE_KEYGUARD:
case TYPE_KEYGUARD_SCRIM:
return false;
default:
@@ -1761,12 +1774,6 @@
android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager");
break;
- case TYPE_KEYGUARD:
- if (mKeyguard != null) {
- return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
- }
- mKeyguard = win;
- break;
case TYPE_KEYGUARD_SCRIM:
if (mKeyguardScrim != null) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
@@ -1783,9 +1790,6 @@
if (mStatusBar == win) {
mStatusBar = null;
mStatusBarController.setWindow(null);
- } else if (mKeyguard == win) {
- Log.v(TAG, "Removing keyguard window (Did it crash?)");
- mKeyguard = null;
mKeyguardDelegate.showScrim();
} else if (mKeyguardScrim == win) {
Log.v(TAG, "Removing keyguard scrim");
@@ -1804,12 +1808,13 @@
if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
+ ": transit=" + transit);
if (win == mStatusBar) {
+ boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
if (transit == TRANSIT_EXIT
|| transit == TRANSIT_HIDE) {
- return R.anim.dock_top_exit;
+ return isKeyguard ? -1 : R.anim.dock_top_exit;
} else if (transit == TRANSIT_ENTER
|| transit == TRANSIT_SHOW) {
- return R.anim.dock_top_enter;
+ return isKeyguard ? -1 : R.anim.dock_top_enter;
}
} else if (win == mNavigationBar) {
// This can be on either the bottom or the right.
@@ -2030,9 +2035,9 @@
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
if (attrs != null) {
final int type = attrs.type;
- if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
- || type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
- || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
+ if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
+ || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
+ || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
// the "app" is keyguard, so give it the key
return 0;
}
@@ -2461,7 +2466,7 @@
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
- if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotHidden()) {
+ if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotOccluded()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
@@ -3083,9 +3088,8 @@
+ mOverscanScreenHeight;
} else if (canHideNavigationBar()
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
- && (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD || (
- attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
- && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
+ && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
// Asking for layout as if the nav bar is hidden, lets the
// application extend into the unrestricted overscan screen area. We
// only do this for application windows to ensure no window that
@@ -3392,16 +3396,19 @@
mForcingShowNavBar = true;
mForcingShowNavBarLayer = win.getSurfaceLayer();
}
+ if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mForceStatusBarFromKeyguard = true;
+ }
if (mTopFullscreenOpaqueWindowState == null &&
win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
- if (attrs.type == TYPE_KEYGUARD) {
+ if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mForceStatusBarFromKeyguard = true;
} else {
mForceStatusBar = true;
}
}
- if (attrs.type == TYPE_KEYGUARD) {
+ if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mShowingLockscreen = true;
}
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
@@ -3531,11 +3538,12 @@
// Hide the key guard if a visible window explicitly specifies that it wants to be
// displayed when the screen is locked.
- if (mKeyguard != null) {
+ if (mKeyguardDelegate != null && mStatusBar != null) {
if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
+ mHideLockScreen);
if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
- if (mKeyguard.hideLw(true)) {
+ mKeyguardHidden = true;
+ if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3549,24 +3557,22 @@
});
}
} else if (mHideLockScreen) {
- if (mKeyguard.hideLw(true)) {
+ mKeyguardHidden = true;
+ if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- if (!mShowingDream) {
- mKeyguardDelegate.setHidden(true);
- }
} else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
// This is the case of keyguard isSecure() and not mHideLockScreen.
if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
// Only launch the next keyguard unlock window once per window.
- if (mKeyguard.showLw(true)) {
+ mKeyguardHidden = false;
+ if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- mKeyguardDelegate.setHidden(false);
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -3576,12 +3582,12 @@
}
} else {
mWinDismissingKeyguard = null;
- if (mKeyguard.showLw(true)) {
+ mKeyguardHidden = false;
+ if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- mKeyguardDelegate.setHidden(false);
}
}
@@ -3596,9 +3602,39 @@
return changes;
}
+ /**
+ * Processes the result code of {@link IKeyguardService#setOccluded}. This is needed because we
+ * immediately need to put the wallpaper directly behind the Keyguard when a window with flag
+ * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} gets dismissed. If we
+ * would wait for Keyguard to change the flags, that would be running asynchronously and thus be
+ * too late so the user might see the window behind.
+ *
+ * @param setHiddenResult The result code from {@link IKeyguardService#setOccluded}.
+ * @return Whether the flags have changed and we have to redo the layout.
+ */
+ private boolean processKeyguardSetHiddenResultLw(int setHiddenResult) {
+ if (setHiddenResult
+ == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS) {
+ mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+ mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ return true;
+ } else if (setHiddenResult
+ == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS) {
+ mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+ mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isStatusBarKeyguard() {
+ return mStatusBar != null
+ && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
+ }
+
public boolean allowAppAnimationsLw() {
- if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()
- || mShowingDream) {
+ if (isStatusBarKeyguard() || mShowingDream) {
// If keyguard or dreams is currently visible, no reason to animate behind it.
return false;
}
@@ -3820,7 +3856,7 @@
// when the keyguard is hidden by another activity.
final boolean keyguardActive = (mKeyguardDelegate == null ? false :
(interactive ?
- mKeyguardDelegate.isShowingAndNotHidden() :
+ mKeyguardDelegate.isShowingAndNotOccluded() :
mKeyguardDelegate.isShowing()));
if (keyCode == KeyEvent.KEYCODE_POWER
@@ -4319,21 +4355,16 @@
private void waitForKeyguard(final ScreenOnListener screenOnListener) {
if (mKeyguardDelegate != null) {
- if (screenOnListener != null) {
- mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
- @Override
- public void onShown(IBinder windowToken) {
- waitForKeyguardWindowDrawn(windowToken, screenOnListener);
- }
- });
- return;
- } else {
- mKeyguardDelegate.onScreenTurnedOn(null);
- }
+ mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
+ @Override
+ public void onShown(IBinder windowToken) {
+ waitForKeyguardWindowDrawn(windowToken, screenOnListener);
+ }
+ });
} else {
Slog.i(TAG, "No keyguard interface!");
+ finishScreenTurningOn(screenOnListener);
}
- finishScreenTurningOn(screenOnListener);
}
private void waitForKeyguardWindowDrawn(IBinder windowToken,
@@ -4346,6 +4377,7 @@
public void sendResult(Bundle data) {
Slog.i(TAG, "Lock screen displayed!");
finishScreenTurningOn(screenOnListener);
+ setKeyguardDrawn();
}
})) {
return;
@@ -4359,6 +4391,7 @@
Slog.i(TAG, "No lock screen! windowToken=" + windowToken);
finishScreenTurningOn(screenOnListener);
+ setKeyguardDrawn();
}
private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
@@ -4402,7 +4435,7 @@
private boolean keyguardIsShowingTq() {
if (mKeyguardDelegate == null) return false;
- return mKeyguardDelegate.isShowingAndNotHidden();
+ return mKeyguardDelegate.isShowingAndNotOccluded();
}
@@ -4439,6 +4472,23 @@
}
}
+ private void setKeyguardDrawn() {
+ synchronized (mLock) {
+ mKeyguardDrawn = true;
+ }
+ try {
+ mWindowManager.enableScreenIfNeeded();
+ } catch (RemoteException unhandled) {
+ }
+ }
+
+ @Override
+ public boolean isKeyguardDrawnLw() {
+ synchronized (mLock) {
+ return mKeyguardDrawn;
+ }
+ }
+
void sendCloseSystemWindows() {
sendCloseSystemWindows(mContext, null);
}
@@ -4722,6 +4772,7 @@
synchronized (mLock) {
mSystemBooted = true;
}
+ waitForKeyguard(null);
}
ProgressDialog mBootMsgDialog = null;
@@ -5046,7 +5097,7 @@
}
final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
- if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotHidden())) {
+ if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotOccluded())) {
return false;
}
long[] pattern = null;
@@ -5097,7 +5148,7 @@
@Override
public void keepScreenOnStoppedLw() {
- if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotHidden()) {
+ if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
}
@@ -5109,7 +5160,7 @@
if (win == null) {
return 0;
}
- if (win.getAttrs().type == TYPE_KEYGUARD && mHideLockScreen == true) {
+ if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
// We are updating at a point where the keyguard has gotten
// focus, but we were last in a state where the top window is
// hiding it. This is probably because the keyguard as been
@@ -5155,8 +5206,8 @@
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
// apply translucent bar vis flags
- WindowState transWin = mKeyguard != null && mKeyguard.isVisibleLw() && !mHideLockScreen
- ? mKeyguard
+ WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
+ ? mStatusBar
: mTopFullscreenOpaqueWindowState;
vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
@@ -5167,9 +5218,10 @@
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.STATUS_BAR_TRANSLUCENT
- | View.NAVIGATION_BAR_TRANSLUCENT;
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ if (!isStatusBarKeyguard() || mHideLockScreen) {
+ flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
+ }
vis = (vis & ~flags) | (oldVis & flags);
}
@@ -5414,15 +5466,13 @@
if (mStatusBar != null) {
pw.print(prefix); pw.print("mStatusBar=");
pw.println(mStatusBar);
+ pw.print(prefix); pw.print("isStatusBarKeyguard=");
+ pw.print(isStatusBarKeyguard());
}
if (mNavigationBar != null) {
pw.print(prefix); pw.print("mNavigationBar=");
pw.println(mNavigationBar);
}
- if (mKeyguard != null) {
- pw.print(prefix); pw.print("mKeyguard=");
- pw.println(mKeyguard);
- }
if (mFocusedWindow != null) {
pw.print(prefix); pw.print("mFocusedWindow=");
pw.println(mFocusedWindow);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 812e817..966924b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -29,8 +29,8 @@
*/
public class KeyguardServiceDelegate {
// TODO: propagate changes to these to {@link KeyguardTouchDelegate}
- public static final String KEYGUARD_PACKAGE = "com.android.keyguard";
- public static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+ public static final String KEYGUARD_PACKAGE = "com.android.systemui";
+ public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
private static final String TAG = "KeyguardServiceDelegate";
private static final boolean DEBUG = true;
@@ -44,13 +44,13 @@
// the event something checks before the service is actually started.
// KeyguardService itself should default to this state until the real state is known.
showing = true;
- showingAndNotHidden = true;
+ showingAndNotOccluded = true;
secure = true;
}
boolean showing;
- boolean showingAndNotHidden;
+ boolean showingAndNotOccluded;
boolean inputRestricted;
- boolean hidden;
+ boolean occluded;
boolean secure;
boolean dreaming;
boolean systemIsReady;
@@ -109,7 +109,7 @@
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
mKeyguardState.showing = false;
- mKeyguardState.showingAndNotHidden = false;
+ mKeyguardState.showingAndNotOccluded = false;
mKeyguardState.secure = false;
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
@@ -148,11 +148,11 @@
return mKeyguardState.showing;
}
- public boolean isShowingAndNotHidden() {
+ public boolean isShowingAndNotOccluded() {
if (mKeyguardService != null) {
- mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden();
+ mKeyguardState.showingAndNotOccluded = mKeyguardService.isShowingAndNotOccluded();
}
- return mKeyguardState.showingAndNotHidden;
+ return mKeyguardState.showingAndNotOccluded;
}
public boolean isInputRestricted() {
@@ -174,11 +174,13 @@
}
}
- public void setHidden(boolean isHidden) {
+ public int setOccluded(boolean isOccluded) {
+ int result = 0;
if (mKeyguardService != null) {
- mKeyguardService.setHidden(isHidden);
+ result = mKeyguardService.setOccluded(isOccluded);
}
- mKeyguardState.hidden = isHidden;
+ mKeyguardState.occluded = isOccluded;
+ return result;
}
public void dismiss() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 9fb2a50..7cb48fa 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -22,6 +22,7 @@
import android.util.Slog;
import android.view.MotionEvent;
+import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
@@ -57,9 +58,9 @@
return false; // TODO cache state
}
- public boolean isShowingAndNotHidden() {
+ public boolean isShowingAndNotOccluded() {
try {
- return mService.isShowingAndNotHidden();
+ return mService.isShowingAndNotOccluded();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
@@ -100,11 +101,12 @@
}
}
- public void setHidden(boolean isHidden) {
+ public int setOccluded(boolean isOccluded) {
try {
- mService.setHidden(isHidden);
+ return mService.setOccluded(isOccluded);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
+ return IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 038686b..3619112 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3013,7 +3013,6 @@
return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
}
- case WindowManager.LayoutParams.TYPE_KEYGUARD:
case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 9768934..5083d44 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -63,6 +63,8 @@
27500 notification_panel_revealed
# when the notification panel is hidden
27501 notification_panel_hidden
+# when notifications are newly displayed on screen, or disappear from screen
+27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3)
# ---------------------------
# Watchdog.java
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 1ed943c..fa803e2 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -35,14 +35,19 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.NativeDaemonConnector.Command;
/**
* Network Service Discovery Service handles remote service discovery operation requests by
@@ -433,14 +438,14 @@
case NativeResponseCode.SERVICE_FOUND:
/* NNN uniqueId serviceName regType domain */
if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw);
- servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
+ servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
clientId, servInfo);
break;
case NativeResponseCode.SERVICE_LOST:
/* NNN uniqueId serviceName regType domain */
if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw);
- servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
+ servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
clientId, servInfo);
break;
@@ -453,7 +458,7 @@
case NativeResponseCode.SERVICE_REGISTERED:
/* NNN regId serviceName regType */
if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw);
- servInfo = new NsdServiceInfo(cooked[2], null, null);
+ servInfo = new NsdServiceInfo(cooked[2], null);
clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
id, clientId, servInfo);
break;
@@ -673,9 +678,22 @@
private boolean registerService(int regId, NsdServiceInfo service) {
if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service);
try {
- //Add txtlen and txtdata
- mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
+ Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(),
service.getServiceType(), service.getPort());
+
+ // Add TXT records as additional arguments.
+ Map<String, byte[]> txtRecords = service.getAttributes();
+ for (String key : txtRecords.keySet()) {
+ try {
+ // TODO: Send encoded TXT record as bytes once NDC/netd supports binary data.
+ cmd.appendArg(String.format(Locale.US, "%s=%s", key,
+ new String(txtRecords.get(key), "UTF_8")));
+ } catch (UnsupportedEncodingException e) {
+ Slog.e(TAG, "Failed to encode txtRecord " + e);
+ }
+ }
+
+ mNativeConnector.execute(cmd);
} catch(NativeDaemonConnectorException e) {
Slog.e(TAG, "Failed to execute registerService " + e);
return false;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index aa756a1..132ca00 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -86,19 +86,19 @@
private final int mRepeat;
private final int mStreamHint;
private final int mUid;
- private final String mPackageName;
+ private final String mOpPkg;
- Vibration(IBinder token, long millis, int streamHint, int uid, String packageName) {
- this(token, millis, null, 0, streamHint, uid, packageName);
+ Vibration(IBinder token, long millis, int streamHint, int uid, String opPkg) {
+ this(token, millis, null, 0, streamHint, uid, opPkg);
}
Vibration(IBinder token, long[] pattern, int repeat, int streamHint, int uid,
- String packageName) {
- this(token, 0, pattern, repeat, streamHint, uid, packageName);
+ String opPkg) {
+ this(token, 0, pattern, repeat, streamHint, uid, opPkg);
}
private Vibration(IBinder token, long millis, long[] pattern,
- int repeat, int streamHint, int uid, String packageName) {
+ int repeat, int streamHint, int uid, String opPkg) {
mToken = token;
mTimeout = millis;
mStartTime = SystemClock.uptimeMillis();
@@ -106,7 +106,7 @@
mRepeat = repeat;
mStreamHint = streamHint;
mUid = uid;
- mPackageName = packageName;
+ mOpPkg = opPkg;
}
public void binderDied() {
@@ -194,7 +194,7 @@
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
- public void vibrate(int uid, String packageName, long milliseconds, int streamHint,
+ public void vibrate(int uid, String opPkg, long milliseconds, int streamHint,
IBinder token) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
!= PackageManager.PERMISSION_GRANTED) {
@@ -211,7 +211,7 @@
return;
}
- Vibration vib = new Vibration(token, milliseconds, streamHint, uid, packageName);
+ Vibration vib = new Vibration(token, milliseconds, streamHint, uid, opPkg);
final long ident = Binder.clearCallingIdentity();
try {
@@ -347,10 +347,10 @@
private void startVibrationLocked(final Vibration vib) {
try {
int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
- vib.mStreamHint, vib.mUid, vib.mPackageName);
+ vib.mStreamHint, vib.mUid, vib.mOpPkg);
if (mode == AppOpsManager.MODE_ALLOWED) {
mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
- AppOpsManager.OP_VIBRATE, vib.mUid, vib.mPackageName);
+ AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
}
if (mode != AppOpsManager.MODE_ALLOWED) {
if (mode == AppOpsManager.MODE_ERRORED) {
@@ -377,7 +377,7 @@
try {
mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
- mCurrentVibration.mPackageName);
+ mCurrentVibration.mOpPkg);
} catch (RemoteException e) {
}
mCurrentVibration = null;
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index e0591a2..ce4c1ed 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -31,4 +31,6 @@
void onPanelRevealed();
void onPanelHidden();
boolean allowDisable(int what, IBinder token, String pkg);
+ void onNotificationVisibilityChanged(
+ String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6534783..5b597a3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1071,6 +1071,16 @@
}
return true;
}
+
+ @Override
+ public void onNotificationVisibilityChanged(
+ String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
+ // Using ';' as separator since eventlogs uses ',' to separate
+ // args.
+ EventLogTags.writeNotificationVisibilityChanged(
+ TextUtils.join(";", newlyVisibleKeys),
+ TextUtils.join(";", noLongerVisibleKeys));
+ }
};
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -1487,9 +1497,9 @@
}
@Override
- public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+ public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
Notification notification, int[] idOut, int userId) throws RemoteException {
- enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(),
+ enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
Binder.getCallingPid(), tag, id, notification, idOut, userId);
}
@@ -1839,14 +1849,14 @@
*/
private final NotificationManagerInternal mInternalService = new NotificationManagerInternal() {
@Override
- public void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
+ public void enqueueNotification(String pkg, String opPkg, int callingUid, int callingPid,
String tag, int id, Notification notification, int[] idReceived, int userId) {
- enqueueNotificationInternal(pkg, basePkg, callingUid, callingPid, tag, id, notification,
+ enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
idReceived, userId);
}
};
- void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
+ void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
int[] idOut, int incomingUserId) {
if (DBG) {
@@ -1971,7 +1981,8 @@
if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
synchronized (mNotificationList) {
final StatusBarNotification n = new StatusBarNotification(
- pkg, id, tag, callingUid, callingPid, score, notification, user);
+ pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
+ user);
NotificationRecord r = new NotificationRecord(n);
NotificationRecord old = null;
@@ -2147,7 +2158,7 @@
// notifying app does not have the VIBRATE permission.
long identity = Binder.clearCallingIdentity();
try {
- mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
+ mVibrator.vibrate(r.sbn.getUid(), r.sbn.getOpPkg(),
useDefaultVibrate ? mDefaultVibrationPattern
: mFallbackVibrationPattern,
((notification.flags & Notification.FLAG_INSISTENT) != 0)
@@ -2158,7 +2169,7 @@
} else if (notification.vibrate.length > 1) {
// If you want your own vibration pattern, you need the VIBRATE
// permission
- mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
+ mVibrator.vibrate(r.sbn.getUid(), r.sbn.getOpPkg(),
notification.vibrate,
((notification.flags & Notification.FLAG_INSISTENT) != 0)
? 0: -1, notification.audioStreamType);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index e4b5f3a..91f796b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -588,6 +588,19 @@
}
@Override
+ public void onNotificationVisibilityChanged(
+ String[] newlyVisibleKeys, String[] noLongerVisibleKeys) throws RemoteException {
+ enforceStatusBarService();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mNotificationDelegate.onNotificationVisibilityChanged(
+ newlyVisibleKeys, noLongerVisibleKeys);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void onClearAllNotifications(int userId) {
enforceStatusBarService();
final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 79c4a50..16ed7fe 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -277,8 +277,14 @@
}
synchronized (mLock) {
sessionState.session = session;
- sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
- sessionToken, sessionState.seq, userId);
+ if (session == null) {
+ removeSessionStateLocked(sessionToken, userId);
+ sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
+ sessionState.seq, userId);
+ } else {
+ sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
+ sessionToken, sessionState.seq, userId);
+ }
}
}
};
@@ -288,6 +294,7 @@
service.createSession(callback);
} catch (RemoteException e) {
Log.e(TAG, "error in createSession", e);
+ removeSessionStateLocked(sessionToken, userId);
sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
sessionState.seq, userId);
}
@@ -307,6 +314,19 @@
}
}
+ private void removeSessionStateLocked(IBinder sessionToken, int userId) {
+ // Remove the session state from the global session state map of the current user.
+ UserState userState = getUserStateLocked(userId);
+ SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
+
+ // Also remove the session state from the session state map of the current service.
+ ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
+ if (serviceState != null) {
+ serviceState.sessionStateMap.remove(sessionToken);
+ }
+ updateServiceConnectionLocked(sessionState.name, userId);
+ }
+
private final class BinderService extends ITvInputManager.Stub {
@Override
public List<TvInputInfo> getTvInputList(int userId) {
@@ -474,17 +494,7 @@
Log.e(TAG, "error in release", e);
}
- // Remove its state from the global session state map of the current user.
- UserState userState = getUserStateLocked(resolvedUserId);
- SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
-
- // Also remove it from the session state map of the current service.
- ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
- if (serviceState != null) {
- serviceState.sessionStateMap.remove(sessionToken);
- }
-
- updateServiceConnectionLocked(sessionState.name, resolvedUserId);
+ removeSessionStateLocked(sessionToken, resolvedUserId);
}
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 7d8b5af..f17b2f4 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
@@ -147,6 +148,9 @@
private int mNextAppTransitionStartWidth;
private int mNextAppTransitionStartHeight;
+ private Rect mTmpFromClipRect = new Rect();
+ private Rect mTmpToClipRect = new Rect();
+
private final static int APP_STATE_IDLE = 0;
private final static int APP_STATE_READY = 1;
private final static int APP_STATE_RUNNING = 2;
@@ -485,7 +489,7 @@
* activity that is leaving, and the activity that is entering.
*/
Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
- int appHeight, int transit,
+ int appHeight, int orientation, int transit,
Rect containingFrame, Rect contentInsets) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
@@ -493,21 +497,36 @@
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
+ // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
+ float scale = 1f;
+ int scaledTopDecor = 0;
+
switch (thumbTransitState) {
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
// Entering app scales up with the thumbnail
- float scale = thumbWidth / appWidth;
- int unscaledThumbHeight = (int) (thumbHeight / scale);
- int scaledTopDecor = (int) (scale * contentInsets.top);
- Rect fromClipRect = new Rect(containingFrame);
- fromClipRect.bottom = (fromClipRect.top + unscaledThumbHeight);
- Rect toClipRect = new Rect(containingFrame);
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // In portrait, we scale the width and clip to the top/left square
+ scale = thumbWidth / appWidth;
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
+ mTmpFromClipRect.set(containingFrame);
+ mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+ mTmpToClipRect.set(containingFrame);
+ } else {
+ // In landscape, we scale the height and clip to the top/left square
+ scale = thumbHeight / (appHeight - contentInsets.top);
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbWidth = (int) (thumbWidth / scale);
+ mTmpFromClipRect.set(containingFrame);
+ mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
+ mTmpToClipRect.set(containingFrame);
+ }
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
computePivot(mNextAppTransitionStartX, scale),
computePivot(mNextAppTransitionStartY, scale));
Animation alphaAnim = new AlphaAnimation(1, 1);
- Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
+ Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
AnimationSet set = new AnimationSet(true);
@@ -539,18 +558,29 @@
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
// Exiting the current app, the app should scale down with the thumbnail
- float scale = thumbWidth / appWidth;
- int unscaledThumbHeight = (int) (thumbHeight / scale);
- int scaledTopDecor = (int) (scale * contentInsets.top);
- Rect fromClipRect = new Rect(containingFrame);
- Rect toClipRect = new Rect(containingFrame);
- toClipRect.bottom = (toClipRect.top + unscaledThumbHeight);
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // In portrait, we scale the width and clip to the top/left square
+ scale = thumbWidth / appWidth;
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
+ mTmpFromClipRect.set(containingFrame);
+ mTmpToClipRect.set(containingFrame);
+ mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+ } else {
+ // In landscape, we scale the height and clip to the top/left square
+ scale = thumbHeight / (appHeight - contentInsets.top);
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbWidth = (int) (thumbWidth / scale);
+ mTmpFromClipRect.set(containingFrame);
+ mTmpToClipRect.set(containingFrame);
+ mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
+ }
Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
computePivot(mNextAppTransitionStartX, scale),
computePivot(mNextAppTransitionStartY, scale));
Animation alphaAnim = new AlphaAnimation(1, 1);
- Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
+ Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
AnimationSet set = new AnimationSet(true);
@@ -637,7 +667,8 @@
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
- int appWidth, int appHeight, Rect containingFrame, Rect contentInsets) {
+ int appWidth, int appHeight, int orientation,
+ Rect containingFrame, Rect contentInsets) {
Animation a;
if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -660,8 +691,8 @@
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
if (mUseAlternateThumbnailAnimation) {
a = createAlternateThumbnailEnterExitAnimationLocked(
- getThumbnailTransitionState(enter), appWidth, appHeight, transit,
- containingFrame, contentInsets);
+ getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
+ transit, containingFrame, contentInsets);
} else {
a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
appWidth, appHeight, transit);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index b27c8d6..f02c0e6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -284,7 +284,7 @@
final boolean hasFocus = (child == mInputFocus);
final boolean isVisible = child.isVisibleLw();
final boolean hasWallpaper = (child == mService.mWallpaperTarget)
- && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
+ && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0;
final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
// If there's a drag in progress and 'child' is a potential drop target,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02d3d57..524d78b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1893,7 +1893,9 @@
int insertionIndex = 0;
if (visible && foundW != null) {
final int type = foundW.mAttrs.type;
- if (type == TYPE_KEYGUARD || type == TYPE_KEYGUARD_SCRIM) {
+ final int privateFlags = foundW.mAttrs.privateFlags;
+ if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
+ || type == TYPE_KEYGUARD_SCRIM) {
insertionIndex = windows.indexOf(foundW);
}
}
@@ -3190,7 +3192,7 @@
}
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
- containingFrame, contentInsets);
+ mCurConfiguration.orientation, containingFrame, contentInsets);
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = null;
@@ -5291,6 +5293,13 @@
performEnableScreen();
}
+ @Override
+ public void enableScreenIfNeeded() {
+ synchronized (mWindowMap) {
+ enableScreenIfNeededLocked();
+ }
+ }
+
void enableScreenIfNeededLocked() {
if (DEBUG_BOOT) {
RuntimeException here = new RuntimeException("here");
@@ -5355,18 +5364,6 @@
final int N = windows.size();
for (int i=0; i<N; i++) {
WindowState w = windows.get(i);
- if (w.mAttrs.type == TYPE_KEYGUARD) {
- // Only if there is a keyguard attached to the window manager
- // will we consider ourselves as having a keyguard. If it
- // isn't attached, we don't know if it wants to be shown or
- // hidden. If it is attached, we will say we have a keyguard
- // if the window doesn't want to be visible, because in that
- // case it explicitly doesn't want to be shown so we should
- // not delay turning the screen on for it.
- boolean vis = w.mViewVisibility == View.VISIBLE
- && w.mPolicyVisibility;
- haveKeyguard = !vis;
- }
if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
return;
}
@@ -5377,8 +5374,8 @@
haveApp = true;
} else if (w.mAttrs.type == TYPE_WALLPAPER) {
haveWallpaper = true;
- } else if (w.mAttrs.type == TYPE_KEYGUARD) {
- haveKeyguard = true;
+ } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
+ haveKeyguard = mPolicy.isKeyguardDrawnLw();
}
}
}
@@ -8335,7 +8332,7 @@
// just don't display").
if (!gone || !win.mHaveFrame || win.mLayoutNeeded
|| ((win.isConfigChanged() || win.setInsetsChanged()) &&
- (win.mAttrs.type == TYPE_KEYGUARD ||
+ ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
win.mAppToken != null && win.mAppToken.layoutConfigChanges))
|| win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
if (!win.mLayoutAttached) {
@@ -8875,8 +8872,8 @@
if (canBeSeen
&& (type == TYPE_SYSTEM_DIALOG
|| type == TYPE_RECENTS_OVERLAY
- || type == TYPE_KEYGUARD
- || type == TYPE_SYSTEM_ERROR)) {
+ || type == TYPE_SYSTEM_ERROR
+ || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
mInnerFields.mSyswin = true;
}
@@ -8889,7 +8886,7 @@
// content on secondary displays (by forcibly enabling mirroring unless
// there is other content we want to show) but still allow opaque
// keyguard dialogs to be shown.
- if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
+ if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
}
mInnerFields.mDisplayHasContent = true;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index dff75ef..4318b0e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -23,12 +23,12 @@
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import android.app.AppOpsManager;
@@ -1010,7 +1010,7 @@
&& (mConfiguration == null
|| (mConfiguration.diff(mService.mCurConfiguration) != 0));
- if (mAttrs.type == TYPE_KEYGUARD) {
+ if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
// Retain configuration changed status until resetConfiguration called.
mConfigHasChanged |= configChanged;
configChanged = mConfigHasChanged;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 35f9314..5a458a3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2905,7 +2905,8 @@
try {
Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
+ Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
} finally {
restoreCallingIdentity(id);
diff --git a/tests/CoreTests/android/core/NsdServiceInfoTest.java b/tests/CoreTests/android/core/NsdServiceInfoTest.java
new file mode 100644
index 0000000..5bf0167
--- /dev/null
+++ b/tests/CoreTests/android/core/NsdServiceInfoTest.java
@@ -0,0 +1,163 @@
+package android.core;
+
+import android.test.AndroidTestCase;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.StrictMode;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+
+public class NsdServiceInfoTest extends AndroidTestCase {
+
+ public final static InetAddress LOCALHOST;
+ static {
+ // Because test.
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+
+ InetAddress _host = null;
+ try {
+ _host = InetAddress.getLocalHost();
+ } catch (UnknownHostException e) { }
+ LOCALHOST = _host;
+ }
+
+ public void testLimits() throws Exception {
+ NsdServiceInfo info = new NsdServiceInfo();
+
+ // Non-ASCII keys.
+ boolean exceptionThrown = false;
+ try {
+ info.setAttribute("猫", "meow");
+ } catch (IllegalArgumentException e) {
+ exceptionThrown = true;
+ }
+ assertTrue(exceptionThrown);
+ assertEmptyServiceInfo(info);
+
+ // ASCII keys with '=' character.
+ exceptionThrown = false;
+ try {
+ info.setAttribute("kitten=", "meow");
+ } catch (IllegalArgumentException e) {
+ exceptionThrown = true;
+ }
+ assertTrue(exceptionThrown);
+ assertEmptyServiceInfo(info);
+
+ // Single key + value length too long.
+ exceptionThrown = false;
+ try {
+ String longValue = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+ "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+ "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+ "ooooooooooooooooooooooooooooong"; // 248 characters.
+ info.setAttribute("longcat", longValue); // Key + value == 255 characters.
+ } catch (IllegalArgumentException e) {
+ exceptionThrown = true;
+ }
+ assertTrue(exceptionThrown);
+ assertEmptyServiceInfo(info);
+
+ // Total TXT record length too long.
+ exceptionThrown = false;
+ int recordsAdded = 0;
+ try {
+ for (int i = 100; i < 300; ++i) {
+ // 6 char key + 5 char value + 2 bytes overhead = 13 byte record length.
+ String key = String.format("key%d", i);
+ info.setAttribute(key, "12345");
+ recordsAdded++;
+ }
+ } catch (IllegalArgumentException e) {
+ exceptionThrown = true;
+ }
+ assertTrue(exceptionThrown);
+ assertTrue(100 == recordsAdded);
+ assertTrue(info.getTxtRecord().length == 1300);
+ }
+
+ public void testParcel() throws Exception {
+ NsdServiceInfo emptyInfo = new NsdServiceInfo();
+ checkParcelable(emptyInfo);
+
+ NsdServiceInfo fullInfo = new NsdServiceInfo();
+ fullInfo.setServiceName("kitten");
+ fullInfo.setServiceType("_kitten._tcp");
+ fullInfo.setPort(4242);
+ fullInfo.setHost(LOCALHOST);
+ checkParcelable(fullInfo);
+
+ NsdServiceInfo noHostInfo = new NsdServiceInfo();
+ noHostInfo.setServiceName("kitten");
+ noHostInfo.setServiceType("_kitten._tcp");
+ noHostInfo.setPort(4242);
+ checkParcelable(noHostInfo);
+
+ NsdServiceInfo attributedInfo = new NsdServiceInfo();
+ attributedInfo.setServiceName("kitten");
+ attributedInfo.setServiceType("_kitten._tcp");
+ attributedInfo.setPort(4242);
+ attributedInfo.setHost(LOCALHOST);
+ attributedInfo.setAttribute("color", "pink");
+ attributedInfo.setAttribute("sound", (new String("にゃあ")).getBytes("UTF-8"));
+ attributedInfo.setAttribute("adorable", (String) null);
+ attributedInfo.setAttribute("sticky", "yes");
+ attributedInfo.setAttribute("siblings", new byte[] {});
+ attributedInfo.setAttribute("edge cases", new byte[] {0, -1, 127, -128});
+ attributedInfo.removeAttribute("sticky");
+ checkParcelable(attributedInfo);
+
+ // Sanity check that we actually wrote attributes to attributedInfo.
+ assertTrue(attributedInfo.getAttributes().keySet().contains("adorable"));
+ String sound = new String(attributedInfo.getAttributes().get("sound"), "UTF-8");
+ assertTrue(sound.equals("にゃあ"));
+ byte[] edgeCases = attributedInfo.getAttributes().get("edge cases");
+ assertTrue(Arrays.equals(edgeCases, new byte[] {0, -1, 127, -128}));
+ assertFalse(attributedInfo.getAttributes().keySet().contains("sticky"));
+ }
+
+ public void checkParcelable(NsdServiceInfo original) {
+ // Write to parcel.
+ Parcel p = Parcel.obtain();
+ Bundle writer = new Bundle();
+ writer.putParcelable("test_info", original);
+ writer.writeToParcel(p, 0);
+
+ // Extract from parcel.
+ p.setDataPosition(0);
+ Bundle reader = p.readBundle();
+ reader.setClassLoader(NsdServiceInfo.class.getClassLoader());
+ NsdServiceInfo result = reader.getParcelable("test_info");
+
+ // Assert equality of base fields.
+ assertEquality(original.getServiceName(), result.getServiceName());
+ assertEquality(original.getServiceType(), result.getServiceType());
+ assertEquality(original.getHost(), result.getHost());
+ assertTrue(original.getPort() == result.getPort());
+
+ // Assert equality of attribute map.
+ Map<String, byte[]> originalMap = original.getAttributes();
+ Map<String, byte[]> resultMap = result.getAttributes();
+ assertEquality(originalMap.keySet(), resultMap.keySet());
+ for (String key : originalMap.keySet()) {
+ assertTrue(Arrays.equals(originalMap.get(key), resultMap.get(key)));
+ }
+ }
+
+ public void assertEquality(Object expected, Object result) {
+ assertTrue(expected == result || expected.equals(result));
+ }
+
+ public void assertEmptyServiceInfo(NsdServiceInfo shouldBeEmpty) {
+ assertTrue(null == shouldBeEmpty.getTxtRecord());
+ }
+}
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml
deleted file mode 100644
index 7adc5af..0000000
--- a/tools/layoutlib/bridge/resources/bars/action_bar.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <include layout="@android:layout/action_bar_home" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-</merge>
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 4dd1446..757cdd2 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -29,6 +29,8 @@
import android.os.RemoteException;
import android.util.DisplayMetrics;
+import java.lang.Override;
+
/**
* Basic implementation of {@link IWindowManager} so that {@link Display} (and
* {@link Display_Delegate}) can return a valid instance.
@@ -453,13 +455,19 @@
}
@Override
- public boolean clearWindowContentFrameStats(IBinder token) {
+ public void enableScreenIfNeeded() throws RemoteException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public boolean clearWindowContentFrameStats(IBinder token) throws RemoteException {
// TODO Auto-generated method stub
return false;
}
@Override
- public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
+ public WindowContentFrameStats getWindowContentFrameStats(IBinder token)
+ throws RemoteException {
// TODO Auto-generated method stub
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java
new file mode 100644
index 0000000..40b6220
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.widget.ActionMenuPresenter;
+
+/**
+ * To access non public members of AbsActionBarView
+ */
+public class ActionBarAccessor {
+
+ /**
+ * Returns the {@link ActionMenuPresenter} associated with the {@link AbsActionBarView}
+ */
+ public static ActionMenuPresenter getActionMenuPresenter(AbsActionBarView view) {
+ return view.mActionMenuPresenter;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index ab4be71..fa8050f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -215,7 +215,8 @@
Capability.ADAPTER_BINDING,
Capability.EXTENDED_VIEWINFO,
Capability.FIXED_SCALABLE_NINE_PATCH,
- Capability.RTL);
+ Capability.RTL,
+ Capability.ACTION_BAR);
BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index f9f4b3a..e0f87fd 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -64,6 +64,11 @@
}
@Override
+ public List<ViewInfo> getSystemRootViews() {
+ return mSession.getSystemViewInfos();
+ }
+
+ @Override
public Map<String, String> getDefaultProperties(Object viewObject) {
return mSession.getDefaultProperties(viewObject);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 9ee2f60..6595ce1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -613,7 +613,8 @@
}
if (value != null) {
- if (value.getFirst() == ResourceType.STYLE) {
+ if ((value.getFirst() == ResourceType.STYLE)
+ || (value.getFirst() == ResourceType.ATTR)) {
// look for the style in the current theme, and its parent:
ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(),
isFrameworkRes);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
new file mode 100644
index 0000000..49027c6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.internal.R;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.widget.ActionBarAccessor;
+import com.android.internal.widget.ActionBarContainer;
+import com.android.internal.widget.ActionBarView;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.ResourceType;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+
+/**
+ * A layout representing the action bar.
+ */
+public class ActionBarLayout extends LinearLayout {
+
+ // Store another reference to the context so that we don't have to cast it repeatedly.
+ @NonNull private final BridgeContext mBridgeContext;
+ @NonNull private final Context mThemedContext;
+
+ @NonNull private final ActionBar mActionBar;
+
+ // Data for Action Bar.
+ @Nullable private final String mIcon;
+ @Nullable private final String mTitle;
+ @Nullable private final String mSubTitle;
+ private final boolean mSplit;
+ private final boolean mShowHomeAsUp;
+ private final int mNavMode;
+
+ // Helper fields.
+ @NonNull private final MenuBuilder mMenuBuilder;
+ private final int mPopupMaxWidth;
+ @NonNull private final RenderResources res;
+ @Nullable private final ActionBarView mActionBarView;
+ @Nullable private FrameLayout mContentRoot;
+ @NonNull private final ActionBarCallback mCallback;
+
+ // A fake parent for measuring views.
+ @Nullable private ViewGroup mMeasureParent;
+
+ public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
+
+ super(context);
+ setOrientation(LinearLayout.HORIZONTAL);
+ setGravity(Gravity.CENTER_VERTICAL);
+
+ // Inflate action bar layout.
+ LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
+ true /*attachToRoot*/);
+ mActionBar = new WindowDecorActionBar(this);
+
+ // Set contexts.
+ mBridgeContext = context;
+ mThemedContext = mActionBar.getThemedContext();
+
+ // Set data for action bar.
+ mCallback = params.getProjectCallback().getActionBarCallback();
+ mIcon = params.getAppIcon();
+ mTitle = params.getAppLabel();
+ // Split Action Bar when the screen size is narrow and the application requests split action
+ // bar when narrow.
+ mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
+ mCallback.getSplitActionBarWhenNarrow();
+ mNavMode = mCallback.getNavigationMode();
+ // TODO: Support Navigation Drawer Indicator.
+ mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
+ mSubTitle = mCallback.getSubTitle();
+
+
+ // Set helper fields.
+ mMenuBuilder = new MenuBuilder(mThemedContext);
+ res = mBridgeContext.getRenderResources();
+ mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
+ mThemedContext.getResources().getDimensionPixelSize(
+ R.dimen.config_prefDialogWidth));
+ mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
+ mContentRoot = (FrameLayout) findViewById(android.R.id.content);
+
+ setupActionBar();
+ }
+
+ /**
+ * Sets up the action bar by filling the appropriate data.
+ */
+ private void setupActionBar() {
+ // Add title and sub title.
+ ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
+ if (titleValue != null && titleValue.getValue() != null) {
+ mActionBar.setTitle(titleValue.getValue());
+ } else {
+ mActionBar.setTitle(mTitle);
+ }
+ if (mSubTitle != null) {
+ mActionBar.setSubtitle(mSubTitle);
+ }
+
+ // Add show home as up icon.
+ if (mShowHomeAsUp) {
+ mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
+ }
+
+ // Set the navigation mode.
+ mActionBar.setNavigationMode(mNavMode);
+ if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
+ setupTabs(3);
+ }
+
+ if (mActionBarView != null) {
+ // If the action bar style doesn't specify an icon, set the icon obtained from the session
+ // params.
+ if (!mActionBarView.hasIcon() && mIcon != null) {
+ Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
+ if (iconDrawable != null) {
+ mActionBar.setIcon(iconDrawable);
+ }
+ }
+
+ // Set action bar to be split, if needed.
+ mActionBarView.setSplitView((ActionBarContainer) findViewById(R.id.split_action_bar));
+ mActionBarView.setSplitActionBar(mSplit);
+
+ inflateMenus();
+ }
+ }
+
+ /**
+ * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
+ * adds them to the action bar.
+ */
+ private void inflateMenus() {
+ if (mActionBarView == null) {
+ return;
+ }
+ final MenuInflater inflater = new MenuInflater(mThemedContext);
+ for (String name : mCallback.getMenuIdNames()) {
+ if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
+ != null) {
+ int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
+ if (id > -1) {
+ inflater.inflate(id, mMenuBuilder);
+ }
+ }
+ }
+ mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
+ }
+
+ // TODO: Use an adapter, like List View to set up tabs.
+ private void setupTabs(int num) {
+ for (int i = 1; i <= num; i++) {
+ Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
+ @Override
+ public void onTabUnselected(Tab t, FragmentTransaction ft) {
+ // pass
+ }
+ @Override
+ public void onTabSelected(Tab t, FragmentTransaction ft) {
+ // pass
+ }
+ @Override
+ public void onTabReselected(Tab t, FragmentTransaction ft) {
+ // pass
+ }
+ });
+ mActionBar.addTab(tab);
+ }
+ }
+
+ @Nullable
+ private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+ ResourceValue value = res.findResValue(name, isFramework);
+ value = res.resolveResValue(value);
+ if (value != null) {
+ return ResourceHelper.getDrawable(value, mBridgeContext);
+ }
+ return null;
+ }
+
+ /**
+ * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to
+ * the content frame which shall serve as the new content root.
+ */
+ public void createMenuPopup() {
+ assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
+ : "Action Bar Menus have already been created.";
+
+ if (!isOverflowPopupNeeded()) {
+ return;
+ }
+
+ // Create a layout to hold the menus and the user's content.
+ RelativeLayout layout = new RelativeLayout(mThemedContext);
+ layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT));
+ mContentRoot.addView(layout);
+ // Create a layout for the user's content.
+ FrameLayout contentRoot = new FrameLayout(mBridgeContext);
+ contentRoot.setLayoutParams(new LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+ // Add contentRoot and menus to the layout.
+ layout.addView(contentRoot);
+ layout.addView(createMenuView());
+ // ContentRoot is now the view we just created.
+ mContentRoot = contentRoot;
+ }
+
+ /**
+ * Returns a {@link LinearLayout} containing the menu list view to be embedded in a
+ * {@link RelativeLayout}
+ */
+ @NonNull
+ private View createMenuView() {
+ DisplayMetrics metrics = mBridgeContext.getMetrics();
+ OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
+
+ LinearLayout layout = new LinearLayout(mThemedContext);
+ RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
+ measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
+ if (mSplit) {
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ // TODO: Find correct value instead of hardcoded 10dp.
+ layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
+ } else {
+ layoutParams.topMargin = getPixelValue("-10dp", metrics);
+ }
+ layout.setLayoutParams(layoutParams);
+ final TypedArray a = mThemedContext.obtainStyledAttributes(null,
+ R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
+ layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
+ layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
+ a.recycle();
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.setDividerPadding(getPixelValue("12dp", metrics));
+ layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
+
+ ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
+ listView.setAdapter(adapter);
+ layout.addView(listView);
+ return layout;
+ }
+
+ private boolean isOverflowPopupNeeded() {
+ boolean needed = mCallback.isOverflowPopupNeeded();
+ if (!needed) {
+ return false;
+ }
+ // Copied from android.widget.ActionMenuPresenter.updateMenuView()
+ ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
+ if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
+ menus != null) {
+ final int count = menus.size();
+ if (count == 1) {
+ needed = !menus.get(0).isActionViewExpanded();
+ } else {
+ needed = count > 0;
+ }
+ }
+ return needed;
+ }
+
+ @Nullable
+ public FrameLayout getContentRoot() {
+ return mContentRoot;
+ }
+
+ // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth()
+ private int measureContentWidth(@NonNull ListAdapter adapter) {
+ // Menus don't tend to be long, so this is more sane than it looks.
+ int maxWidth = 0;
+ View itemView = null;
+ int itemType = 0;
+
+ final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ final int count = adapter.getCount();
+ for (int i = 0; i < count; i++) {
+ final int positionType = adapter.getItemViewType(i);
+ if (positionType != itemType) {
+ itemType = positionType;
+ itemView = null;
+ }
+
+ if (mMeasureParent == null) {
+ mMeasureParent = new FrameLayout(mThemedContext);
+ }
+
+ itemView = adapter.getView(i, itemView, mMeasureParent);
+ itemView.measure(widthMeasureSpec, heightMeasureSpec);
+
+ final int itemWidth = itemView.getMeasuredWidth();
+ if (itemWidth >= mPopupMaxWidth) {
+ return mPopupMaxWidth;
+ } else if (itemWidth > maxWidth) {
+ maxWidth = itemWidth;
+ }
+ }
+
+ return maxWidth;
+ }
+
+ private int getPixelValue(@NonNull String value, @NonNull DisplayMetrics metrics) {
+ TypedValue typedValue = ResourceHelper.getValue(null, value, false /*requireUnit*/);
+ return (int) typedValue.getDimension(metrics);
+ }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
deleted file mode 100644
index 226649d..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class FakeActionBar extends CustomBar {
-
- private TextView mTextView;
-
- public FakeActionBar(Context context, Density density, String label, String icon)
- throws XmlPullParserException {
- super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml");
-
- // Cannot access the inside items through id because no R.id values have been
- // created for them.
- // We do know the order though.
- loadIconById(android.R.id.home, icon);
- mTextView = setText(1, label);
-
- setStyle("actionBarStyle");
- }
-
- @Override
- protected TextView getStyleableTextView() {
- return mTextView;
- }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java
new file mode 100644
index 0000000..778305d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuView;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.util.ArrayList;
+
+/**
+ * Provides an adapter for Overflow menu popup. This is very similar to
+ * {@code MenuPopupHelper.MenuAdapter}
+ */
+public class OverflowMenuAdapter extends BaseAdapter {
+
+ private final MenuBuilder mMenu;
+ private int mExpandedIndex = -1;
+ private final Context context;
+
+ public OverflowMenuAdapter(MenuBuilder menu, Context context) {
+ mMenu = menu;
+ findExpandedIndex();
+ this.context = context;
+ }
+
+ @Override
+ public int getCount() {
+ ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+ if (mExpandedIndex < 0) {
+ return items.size();
+ }
+ return items.size() - 1;
+ }
+
+ @Override
+ public MenuItemImpl getItem(int position) {
+ ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+ if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
+ position++;
+ }
+ return items.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ // Since a menu item's ID is optional, we'll use the position as an
+ // ID for the item in the AdapterView
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ LayoutInflater mInflater = LayoutInflater.from(context);
+ convertView = mInflater.inflate(com.android.internal.R.layout.popup_menu_item_layout,
+ parent, false);
+ }
+
+ MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+ itemView.initialize(getItem(position), 0);
+ return convertView;
+ }
+
+ private void findExpandedIndex() {
+ final MenuItemImpl expandedItem = mMenu.getExpandedItem();
+ if (expandedItem != null) {
+ final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+ final int count = items.size();
+ for (int i = 0; i < count; i++) {
+ final MenuItemImpl item = items.get(i);
+ if (item == expandedItem) {
+ mExpandedIndex = i;
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 377d996..afcadef 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -43,12 +43,13 @@
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.bars.FakeActionBar;
import com.android.layoutlib.bridge.bars.NavigationBar;
import com.android.layoutlib.bridge.bars.StatusBar;
import com.android.layoutlib.bridge.bars.TitleBar;
+import com.android.layoutlib.bridge.bars.ActionBarLayout;
import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
+import com.android.resources.Density;
import com.android.resources.ResourceType;
import com.android.resources.ScreenOrientation;
import com.android.util.Pair;
@@ -134,6 +135,7 @@
// information being returned through the API
private BufferedImage mImage;
private List<ViewInfo> mViewInfoList;
+ private List<ViewInfo> mSystemViewInfoList;
private static final class PostInflateException extends Exception {
private static final long serialVersionUID = 1L;
@@ -146,10 +148,11 @@
/**
* Creates a layout scene with all the information coming from the layout bridge API.
* <p>
- * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a
+ * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
+ * which act as a
* call to {@link RenderSessionImpl#acquire(long)}
*
- * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
+ * @see Bridge#createSession(SessionParams)
*/
public RenderSessionImpl(SessionParams params) {
super(new SessionParams(params));
@@ -225,14 +228,15 @@
HardwareConfig hardwareConfig = params.getHardwareConfig();
BridgeContext context = getContext();
boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
- int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+ int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+ ActionBarLayout actionBar = null;
// the view group that receives the window background.
ViewGroup backgroundView = null;
if (mWindowIsFloating || params.isForceNoDecor()) {
backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
- mViewRoot.setLayoutDirection(direction);
+ mViewRoot.setLayoutDirection(layoutDirection);
} else {
if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
/*
@@ -254,18 +258,13 @@
the bottom
*/
LinearLayout topLayout = new LinearLayout(context);
- topLayout.setLayoutDirection(direction);
+ topLayout.setLayoutDirection(layoutDirection);
mViewRoot = topLayout;
topLayout.setOrientation(LinearLayout.HORIZONTAL);
try {
- NavigationBar navigationBar = new NavigationBar(context,
- hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
- params.isRtlSupported());
- navigationBar.setLayoutParams(
- new LinearLayout.LayoutParams(
- mNavigationBarSize,
- LayoutParams.MATCH_PARENT));
+ NavigationBar navigationBar = createNavigationBar(context,
+ hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
topLayout.addView(navigationBar);
} catch (XmlPullParserException e) {
@@ -293,14 +292,15 @@
LinearLayout topLayout = new LinearLayout(context);
topLayout.setOrientation(LinearLayout.VERTICAL);
- topLayout.setLayoutDirection(direction);
+ topLayout.setLayoutDirection(layoutDirection);
// if we don't already have a view root this is it
if (mViewRoot == null) {
mViewRoot = topLayout;
} else {
+ int topLayoutWidth =
+ params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
- layoutParams.weight = 1;
+ topLayoutWidth, LayoutParams.MATCH_PARENT);
topLayout.setLayoutParams(layoutParams);
// this is the case of soft buttons + vertical bar.
@@ -319,12 +319,9 @@
if (mStatusBarSize > 0) {
// system bar
try {
- StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
- direction, params.isRtlSupported());
- systemBar.setLayoutParams(
- new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, mStatusBarSize));
- topLayout.addView(systemBar);
+ StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
+ layoutDirection, params.isRtlSupported());
+ topLayout.addView(statusBar);
} catch (XmlPullParserException e) {
}
@@ -343,23 +340,17 @@
// if the theme says no title/action bar, then the size will be 0
if (mActionBarSize > 0) {
try {
- FakeActionBar actionBar = new FakeActionBar(context,
- hardwareConfig.getDensity(),
- params.getAppLabel(), params.getAppIcon());
- actionBar.setLayoutParams(
- new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, mActionBarSize));
+ actionBar = createActionBar(context, params);
backgroundLayout.addView(actionBar);
+ actionBar.createMenuPopup();
+ mContentRoot = actionBar.getContentRoot();
} catch (XmlPullParserException e) {
}
} else if (mTitleBarSize > 0) {
try {
- TitleBar titleBar = new TitleBar(context,
+ TitleBar titleBar = createTitleBar(context,
hardwareConfig.getDensity(), params.getAppLabel());
- titleBar.setLayoutParams(
- new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, mTitleBarSize));
backgroundLayout.addView(titleBar);
} catch (XmlPullParserException e) {
@@ -367,23 +358,21 @@
}
// content frame
- mContentRoot = new FrameLayout(context);
- layoutParams = new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, 0);
- layoutParams.weight = 1;
- mContentRoot.setLayoutParams(layoutParams);
- backgroundLayout.addView(mContentRoot);
+ if (mContentRoot == null) {
+ mContentRoot = new FrameLayout(context);
+ layoutParams = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, 0);
+ layoutParams.weight = 1;
+ mContentRoot.setLayoutParams(layoutParams);
+ backgroundLayout.addView(mContentRoot);
+ }
if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
mNavigationBarSize > 0) {
// system bar
try {
- NavigationBar navigationBar = new NavigationBar(context,
- hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
- params.isRtlSupported());
- navigationBar.setLayoutParams(
- new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, mNavigationBarSize));
+ NavigationBar navigationBar = createNavigationBar(context,
+ hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
topLayout.addView(navigationBar);
} catch (XmlPullParserException e) {
@@ -441,7 +430,7 @@
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see RenderParams#getRenderingMode()
+ * @see SessionParams#getRenderingMode()
* @see RenderSession#render(long)
*/
public Result render(boolean freshRender) {
@@ -584,7 +573,7 @@
mViewRoot.draw(mCanvas);
}
- mViewInfoList = startVisitingViews(mViewRoot, 0, params.getExtendedViewInfoMode());
+ mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), false);
// success!
return SUCCESS.createResult();
@@ -1369,50 +1358,126 @@
}
}
- private List<ViewInfo> startVisitingViews(View view, int offset, boolean setExtendedInfo) {
- if (view == null) {
- return null;
- }
-
- // adjust the offset to this view.
- offset += view.getTop();
-
- if (view == mContentRoot) {
- return visitAllChildren(mContentRoot, offset, setExtendedInfo);
- }
-
- // otherwise, look for mContentRoot in the children
- if (view instanceof ViewGroup) {
- ViewGroup group = ((ViewGroup) view);
-
- for (int i = 0; i < group.getChildCount(); i++) {
- List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset,
- setExtendedInfo);
- if (list != null) {
- return list;
- }
- }
- }
-
- return null;
- }
-
/**
- * Visits a View and its children and generate a {@link ViewInfo} containing the
+ * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
* bounds of all the views.
+ *
* @param view the root View
* @param offset an offset for the view bounds.
* @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+ * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
+ * content frame.
+ *
+ * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
*/
- private ViewInfo visit(View view, int offset, boolean setExtendedInfo) {
+ private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
+ boolean isContentFrame) {
+ ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
+
+ if (view instanceof ViewGroup) {
+ ViewGroup group = ((ViewGroup) view);
+ result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
+ setExtendedInfo, isContentFrame));
+ }
+ return result;
+ }
+
+ /**
+ * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
+ * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
+ * the children of the {@code mContentRoot}.
+ *
+ * @param viewGroup the root View
+ * @param offset an offset from the top for the content view frame.
+ * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+ * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
+ * content frame. {@code false} if the {@code ViewInfo} to be created is
+ * part of the system decor.
+ */
+ private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
+ boolean setExtendedInfo, boolean isContentFrame) {
+ if (viewGroup == null) {
+ return null;
+ }
+
+ if (!isContentFrame) {
+ offset += viewGroup.getTop();
+ }
+
+ int childCount = viewGroup.getChildCount();
+ if (viewGroup == mContentRoot) {
+ List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
+ List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
+ for (int i = 0; i < childCount; i++) {
+ ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
+ setExtendedInfo);
+ childrenWithoutOffset.add(childViewInfo[0]);
+ childrenWithOffset.add(childViewInfo[1]);
+ }
+ mViewInfoList = childrenWithOffset;
+ return childrenWithoutOffset;
+ } else {
+ List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
+ for (int i = 0; i < childCount; i++) {
+ children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
+ isContentFrame));
+ }
+ return children;
+ }
+ }
+
+ /**
+ * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
+ * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
+ * one with the {@code offset} and other without the {@code offset}. The offset is needed to
+ * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
+ * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
+ * offset is not needed.
+ *
+ * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
+ * index 1 is with the offset.
+ */
+ private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
+ ViewInfo[] result = new ViewInfo[2];
+ if (view == null) {
+ return result;
+ }
+
+ result[0] = createViewInfo(view, 0, setExtendedInfo, true);
+ result[1] = createViewInfo(view, offset, setExtendedInfo, true);
+ if (view instanceof ViewGroup) {
+ List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
+ result[0].setChildren(children);
+ result[1].setChildren(children);
+ }
+ return result;
+ }
+
+ /**
+ * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
+ * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
+ * set.
+ * @param offset an offset for the view bounds. Used only if view is part of the content frame.
+ */
+ private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
+ boolean isContentFrame) {
if (view == null) {
return null;
}
- ViewInfo result = new ViewInfo(view.getClass().getName(),
- getContext().getViewKey(view),
- view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
- view, view.getLayoutParams());
+ ViewInfo result;
+ if (isContentFrame) {
+ result = new ViewInfo(view.getClass().getName(),
+ getContext().getViewKey(view),
+ view.getLeft(), view.getTop() + offset, view.getRight(),
+ view.getBottom() + offset, view, view.getLayoutParams());
+
+ } else {
+ result = new SystemViewInfo(view.getClass().getName(),
+ getContext().getViewKey(view),
+ view.getLeft(), view.getTop(), view.getRight(),
+ view.getBottom(), view, view.getLayoutParams());
+ }
if (setExtendedInfo) {
MarginLayoutParams marginParams = null;
@@ -1427,39 +1492,67 @@
marginParams != null ? marginParams.bottomMargin : 0);
}
- if (view instanceof ViewGroup) {
- ViewGroup group = ((ViewGroup) view);
- result.setChildren(visitAllChildren(group, 0 /*offset*/, setExtendedInfo));
- }
-
return result;
}
- /**
- * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
- * containing the bounds of all the views.
- * @param view the root View
- * @param offset an offset for the view bounds.
- * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
- */
- private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
- boolean setExtendedInfo) {
- if (viewGroup == null) {
- return null;
- }
-
- List<ViewInfo> children = new ArrayList<ViewInfo>();
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo));
- }
- return children;
- }
-
-
private void invalidateRenderingSize() {
mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
}
+ /**
+ * Creates the status bar with wifi and battery icons.
+ */
+ private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
+ boolean isRtlSupported) throws XmlPullParserException {
+ StatusBar statusBar = new StatusBar(context, density,
+ direction, isRtlSupported);
+ statusBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mStatusBarSize));
+ return statusBar;
+ }
+
+ /**
+ * Creates the navigation bar with back, home and recent buttons.
+ *
+ * @param isRtl true if the current locale is right-to-left
+ * @param isRtlSupported true is the project manifest declares that the application
+ * is RTL aware.
+ */
+ private NavigationBar createNavigationBar(BridgeContext context, Density density,
+ boolean isRtl, boolean isRtlSupported) throws XmlPullParserException {
+ NavigationBar navigationBar = new NavigationBar(context,
+ density, mNavigationBarOrientation, isRtl,
+ isRtlSupported);
+ if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
+ navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
+ LayoutParams.MATCH_PARENT));
+ } else {
+ navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ mNavigationBarSize));
+ }
+ return navigationBar;
+ }
+
+ private TitleBar createTitleBar(BridgeContext context, Density density, String title)
+ throws XmlPullParserException {
+ TitleBar titleBar = new TitleBar(context, density, title);
+ titleBar.setLayoutParams(
+ new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
+ return titleBar;
+ }
+
+ /**
+ * Creates the action bar. Also queries the project callback for missing information.
+ */
+ private ActionBarLayout createActionBar(BridgeContext context, SessionParams params)
+ throws XmlPullParserException {
+ ActionBarLayout actionBar = new ActionBarLayout(context, params);
+ actionBar.setLayoutParams(new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+ return actionBar;
+ }
+
public BufferedImage getImage() {
return mImage;
}
@@ -1472,6 +1565,10 @@
return mViewInfoList;
}
+ public List<ViewInfo> getSystemViewInfos() {
+ return mSystemViewInfoList;
+ }
+
public Map<String, String> getDefaultProperties(Object viewObject) {
return getContext().getDefaultPropMap(viewObject);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 6dcb693..adb0937 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -165,6 +165,9 @@
* @param context the current context
*/
public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
+ if (value == null) {
+ return null;
+ }
String stringValue = value.getValue();
if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
new file mode 100644
index 0000000..5c267df
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.impl;
+
+import com.android.ide.common.rendering.api.ViewInfo;
+
+public class SystemViewInfo extends ViewInfo {
+
+ public SystemViewInfo(String name, Object cookie, int left, int top,
+ int right, int bottom) {
+ super(name, cookie, left, top, right, bottom);
+ }
+
+ public SystemViewInfo(String name, Object cookie, int left, int top,
+ int right, int bottom, Object viewObject, Object layoutParamsObject) {
+ super(name, cookie, left, top, right, bottom, viewObject,
+ layoutParamsObject);
+ }
+
+ @Override
+ public boolean isSystemView() {
+ return true;
+ }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 7c3ab6f..2e952fc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -116,6 +116,7 @@
"com.android.i18n.phonenumbers.*", // for TextView with autolink attribute
"android.app.DatePickerDialog", // b.android.com/28318
"android.app.TimePickerDialog", // b.android.com/61515
+ "com.android.internal.view.menu.ActionMenu",
},
excludeClasses,
new String[] {