WQMY
Ali Golden | LinkedIn
Ali Golden. server at Namans Catering. Location: Mobile, Alabama (Mobile, Alabama Area); Industry: Food & Beverages .
http://www.linkedin.com/pub/ali-golden/58/252/759
Gulf Shores Caterers, Catering, AL
Alec Naman Catering Mobile, AL,<PHONE_NUMBER>. Caterers: Naman's Catering is the Premier Caterer servicing the Gulf Coast for over 15 years. Naman's .
http://www.gatheringguide.com/event_directory/rc/al_alabama/gulf_shores/evl_caterers_catering.html
Alec Naman Catering - Mobile, Alabama - Yahoo! Travel
Alec Naman Catering, Mobile - find photos, descriptions, maps, reviews, and expert advice on Yahoo! Travel.
http://travel.yahoo.com/p-travelguide-14870283R-alec_naman_catering-i
Contents |
[newton's laws project gifted] History
Maysoon Sayyad | LinkedIn
Maysoon Sayyad. Event Planner at Naman's Catering. Location: Mobile, Alabama Area; Industry: Events Services. Join LinkedIn and access Maysoon Sayyad's .
http://www.linkedin.com/pub/maysoon-sayyad/1a/93a/31
Naman's Catering, Mobile, Alabama (AL) - Catering Service, Mobile ...
Schedule Naman's Catering in Mobile, Alabama (AL) for your event. Use Eventective to find Caterer vendors for your meeting, event, wedding, or banquet.
http://www.eventective.com/USA/Alabama/Mobile/182308/
Namans Catering Reviews & Ratings, Wedding Catering, Florida ...
Read reviews about Namans Catering. Compare thousands of Wedding Catering ratings in Florida - Panhandle, Mobile, and surrounding . Mobile, AL 36618 .
http://www.weddingwire.com/reviews/namans-catering-mobile/bae3f8680370b506.html
Alec Naman Catering - Mobile, AL (Alabama) |<PHONE_NUMBER>
Naman's Catering has been the Premier Caterer for the Gulf Coast for over 20 years, serving Mobile County, Baldwin County, and Mississippi Gulf Coast.
http://www.manta.com/c/mm50bwk/alec-naman-catering
Naman's Catering - Alabama
Naman's Catering. The Knot Best of Weddings. 1909 Brookdale Drive West Mobile, AL 36618-0000 map |<PHONE_NUMBER>. | Serving Area: Alabama .
http://www.theknot.com/vendors/namans-catering/profile/cat/203/223309/profile
Alec Naman | LinkedIn
View Alec Naman's professional profile on LinkedIn. . president at naman's catering inc . Event Specialist at City of Mobile, AL; Sherri Grubbs, MBA, SPHR .
http://www.linkedin.com/pub/alec-naman/11/a03/432
Wedding Catering | Naman's Catering
If you want something more relaxed and social, the hors de oeuvres style menu .
http://www.namanscatering.com/catering/?page_id=2542
Weddings Catering In AL Alabama Business listings for Weddings ...
Abigails Catering LLC 1021 Noble St Anniston, AL 36201-4607<PHONE_NUMBER>. Alec Naman Catering 1909 Brookdale Dr W Mobile, AL 36618-1118 (251)473- .
http://nealcomm.com/AL-Alabama/Weddings-Catering/
Contact Us | Naman's Catering
. Traditional Dinner Menu · Hors d' oeuvres Menu · Contact Us · Recipes .
http://www.namanscatering.com/catering/?page_id=2693
Mobile, - AL - Wedding Caterer - Party Catering - Birthday - Events ...
Premier Catering! Voted "Best Of The Bay" 19 Years Experience! Local:<PHONE_NUMBER>. NAMAN'S CATERING, INC. 1909 Brookdale Dr W Mobile, AL 36618 .
http://www.weddingandpartynetwork.com/c/Caterers-Food-and-Beverages/l/Alabama/Mobile
Wedding Catering Venus | Naman's Catering
If you want something more relaxed and social, the hors de oeuvres style menu .
http://www.namanscatering.com/catering/?page_id=2651
Bellingrath Gardens and Home - Weddings & Receptions
Bellingrath Gardens and Home, Mobile Alabama. . Catering at Bellingrath Gardens is exclusively handled by Naman's Catering of Mobile<PHONE_NUMBER>).
http://www.bellingrath.org/weddings/receptions.html
[500ms time delay circuit] Digital channels
| Channel | Name | look up licenses for nurses | traditinal swedish christmas dinner | Programming |
|---|---|---|---|---|
| 53.1 | naman's catering mobile al DT | longitude latitude maps for teachers | recipe salted roasted peanuts in shell | Main naman's catering mobile al programming / MyNetworkTV |
| 53.2 | WOLF DT | winter garden check list | mettam coat of arms | Simulcast of eva second wedding dress |
| 53.3 | WSWB DT | 480i | 4:3 | Simulcast of cat litter dust free |
Alabama Wedding Caterers and Catering
Local Alabama wedding caterers are listed in our planning guide. For your . Naman's Catering is the Award Winning Premier Caterer on the Gulf Coast serving Alabama and . We serve 50 to 5000 guest with "Atten Mobile, AL<PHONE_NUMBER> .
http://www.allweddingcompanies.com/catering/caterers/alabama/
[book chapter a blushing girl ballam] References
[knights of the rising sun jefferson] External links
- bracewell sahara car crossing
- south american noni juice
- harcourt trophies reading stories
- martial arts flowery branch ga
- electric specialty vehicles for disablities
- roika tarangire tented lodge
|
|


- Robert A. Heinlein
"Not all shapes are as well-behaved as circles."
- Matt Parker
"Identity theft is not a joke Jim!" - Dwight Schrute
"Sometimes I'll start a sentence and I don't even know where it's going. I just hope I find it along the way." - Michael Scott
"Every great story seems to begin with a snake." - Nicholas Cage
"Couldn’t think of a witty quote" -Versilis Tyson
"There's no map to human behaviour". - Bjork


Go to the source code of this file.
Defines | |
| #define | SA_LEN(sa) (sizeof(struct sockaddr)) |
| #define | SS_LEN(ss) (sizeof(struct sockaddr)) |
| #define | SET_SA_LEN(sa, len) (void)(len) |
| #define | SET_SS_LEN(ss, len) (void)(len) |
| #define | SIN_LEN(si) sizeof(struct sockaddr_in) |
| #define | SET_SIN_LEN(si, len) |
| #define | IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) |
| #define | IN_MULTICAST(i) IN_CLASSD(i) |
| #define | IN_EXPERIMENTAL(i) ((((long)(i)) & 0xe0000000) == 0xe0000000) |
| #define | IN_CLASSA_NSHIFT 24 |
| #define | IN_LOOPBACKNET 127 |
| #define | AF_UNSPEC 0 |
| #define | PF_UNSPEC AF_UNSPEC |
| #define | PF_INET AF_INET |
| #define AF_UNSPEC 0 |
Definition at line 69 of file sockport.h.
Referenced by get_addr(), get_afamily(), open_ifs_socket(), rsock_addrinfo(), rsock_getfamily(), sockopt_inspect(), and sockopt_s_linger().
| #define IN_CLASSA_NSHIFT 24 |
Definition at line 61 of file sockport.h.
Referenced by getaddrinfo(), and getnameinfo().
| #define IN_CLASSD | ( | i | ) | (((long)(i) & 0xf0000000) == 0xe0000000) |
Definition at line 52 of file sockport.h.
| #define IN_EXPERIMENTAL | ( | i | ) | ((((long)(i)) & 0xe0000000) == 0xe0000000) |
Definition at line 57 of file sockport.h.
Referenced by getaddrinfo(), and getnameinfo().
| #define IN_LOOPBACKNET 127 |
Definition at line 65 of file sockport.h.
Referenced by getaddrinfo().
| #define IN_MULTICAST | ( | i | ) | IN_CLASSD(i) |
Definition at line 53 of file sockport.h.
Referenced by getaddrinfo(), and getnameinfo().
| #define PF_INET AF_INET |
Definition at line 77 of file sockport.h.
Referenced by addrinfo_inspect(), getaddrinfo(), and socketpair_internal().
| #define PF_UNSPEC AF_UNSPEC |
Definition at line 73 of file sockport.h.
Referenced by addrinfo_initialize(), addrinfo_s_ip(), addrinfo_s_tcp(), addrinfo_s_udp(), call_getaddrinfo(), getaddrinfo(), sock_s_getaddrinfo(), and sock_s_getnameinfo().
| #define SA_LEN | ( | sa | ) | (sizeof(struct sockaddr)) |
Definition at line 29 of file sockport.h.
Referenced by getnameinfo(), make_ipaddr0(), rsock_ipaddr(), and sock_s_getnameinfo().
Definition at line 39 of file sockport.h.
| #define SET_SIN_LEN | ( | si, | |||
| len | ) |
Definition at line 48 of file sockport.h.
Referenced by make_inetaddr().
Definition at line 40 of file sockport.h.
| #define SIN_LEN | ( | si | ) | sizeof(struct sockaddr_in) |
Definition at line 47 of file sockport.h.
| #define SS_LEN | ( | ss | ) | (sizeof(struct sockaddr)) |
Definition at line 30 of file sockport.h.
Referenced by sock_s_getnameinfo().


I am very excited to start my work here with Udacity. I work full time for at&t. I just completed my bachelors and ready to complete multiple nanodegrees for my career transistion into IT.
I have made multiple html pages using dreamweaver. Even though this a very simple course for me so far, I hope to have my brain tested with python language later.
It is almost summer time. That means it is time to pick a tropical destination to visit for a vacation! Definitely a needed trip here soon!


THE WORLD IS NOT ENOUGH A film review by Steve Rhodes Copyright 1999 Steve Rhodes RATING (0 TO ****): ***
Some movies shoot for the moon. Others wallow in the dirt. Bond films, on the other hand, have modest, simple aspirations. They are happy just to provide solid entertainment value. And by that metric, THE WORLD IS NOT ENOUGH, directed by 42 UP's Michael Apted, does exactly what it sets out to do. Pierce Brosnan in his best film yet as James Bond, proves once again that he's the best Bond since Sean Connery.
The most important costars in the Bond movies are the spy's toys. These films usually have the audience applauding for the stunts, and this episode of the superspy saga is no different.
 The vehicle even has the ability to dive underwater briefly while the driver holds his breath. It can turn into a car as well, all the better to engage in a typical Bond demolition derby.
The plot, not that it's important, involves competing oil pipelines and stolen plutonium. "If there's the slightest chance, Bond will succeed," his boss, M (Judi Dench), reassures us. The outcome of a Bond movie is never in question, but who cares? That's not why we're here. We come to have fun and enjoy the action, like the helicopter with a supersized chainsaw attached, which cuts through cars and buildings.
Elektra King (Sophie Marceau) is a recently kidnapped daughter of a wealthy oil magnate who's building a large oil pipeline in competition with 3 other Russian ones. Sophie Marceau, who possesses the eternal beauty of a lush oil painting, has a knack, as she showed in FIRELIGHT, for appearing hopelessly vulnerable while being anything but. Bond films always feature beautiful women, and the two this time are among the best of the Bond babes.
Besides Marceau, the sexually charged Denise Richards (WILD THINGS) plays Dr. Christmas Jones, a nuclear physicist with explosive good looks. First seen in a tight fitting tank top and brief shorts, she makes science look pretty exciting. Under Apted's direction, both of the women hold their own against the world's best spy. King is deceptively alluring, and Jones is young and cocky. "You want to put that into English for those of us who don't speak spy?" Jones mocks Bond at one point.
After an injury, Bond seduces M5's female doctor in order to be declared fit for service. "He has remarkable stamina," her report concludes. The movie is rife with such double-entendres, which delight the older members of the audience while going right over the heads of the younger.
In a cameo John Cleese plays R, the replacement that Q's been training. R goes over all of the bells, whistles and guns in Bond's latest spymobile. This one, R tells him, even has 6 cup holders.

Bond movies don't really have messages. They're happy just to amuse us, which this one does in spades with its great stunts, funny dialog and crisp acting. On the other hand, if we want to go looking for a message, Bond himself says it best. Stunningly handsome, lying in bed next to the equally beautiful King, he tells her, "I take pleasure in great beauty." Now that's something with which viewers of either sex can identify.
THE WORLD IS NOT ENOUGH runs 2:08. It is rated PG-13 for intense sequences of action violence, some sexuality and innuendo and would be acceptable for kids around 10 or 11 and up.
My son Jeffrey, age 10, who has seen all but 2 of the Bond films, loved this one, giving it ****. He especially liked the battles and the boat/sub/car. His friends, ages 10 and 11, with him mentioned the same things, and had similar ratings -- Steven ****, Nickolas ****, John *** 1/2 and Alan ***. Alan and John complained that there was too much sleeping around. (There is no sex or nudity in the film, and the women are strategically covered by the bedcovers.)
Email<EMAIL_ADDRESS>Web: http://www.InternetReviews.com
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Methods
| Modifier and Type |
Method and Description |
java.util.ArrayList<Move> |
calculateValidMoves(Cell[][] board,
Cell curr) |
Cell[][] |
copyBoard(Cell[][] currentBoard) |
private int[][] |
cornerGroup() |
private double |
cornerHeurisitc(Cell maxPlayer,
Cell[][] currentBoard) |
private double |
cornerProximity(Cell maxPlayer,
Cell[][] currentBoard) |
private int |
directionCount(int[] shift,
int xCoordinate,
int yCoordinate,
Cell currentPlayer,
Cell[][] board,
int stepCount) |
double |
evalutationFunction(Cell maxPlayer,
Cell[][] currentBoard,
int sign) |
int[] |
getArrayShift(Direction d) |
private double |
immediateMobility(Cell maxPlayer,
Cell[][] currentBoard) |
private boolean |
inboundsCheck(int x,
int y) |
Cell[][] |
makeMove(Move move,
Cell[][] board,
Cell currentPlayer) |
Cell |
nextPlayer(Cell player) |
private double |
scoreDifferential(Cell maxPlayer,
Cell[][] currentBoard) |
private double |
wipeOut(Cell maxPlayer,
Cell[][] currentBoard) |


CSS Sythax Formal Parser
Choose a formal synthaxe or write your own:
or
String to test:
Result:
Next values:
Run tests
(open debugger to see logs)


We exchange mices!
- monetize end-to-end web services
- transform B2B communities
- strategize robust infrastructures
- seize ubiquitous e-business
- integrate innovative niches
- incentivize granular functionalities
- drive value-added e-services
- incubate 24/7 systems
- integrate cutting-edge markets
- seize cross-media infomediaries
- unleash proactive partnerships
- envisioneer magnetic partnerships
- recontextualize proactive communities
- generate end-to-end channels


Rio Grande (1950)
Grade: 68
"Rio Grande" was the third chapter of director John Ford's cavalry trilogy, after "Fort Apache" and "She Wore a Yellow Ribbon". Much of the cast and crew from those features returns, including John Wayne, comic relief Victor McLaglen, Jack Pennick, and writer James Warner Bellah.
"Rio Grande" is set at a remote, undestaffed fort near the Mexican border in 1879. Lt. Col. Yorke (John Wayne) is facing an uprising of Apache Indians, who emerge from protected villages in Mexico for hit and run attacks. Yorke's young son has failed West Point and enlisted to prove his manhood, by coincidence assigned to his father's command. Wayne's estranged wife Kathleen (Maureen O'Hara) arrives to claim her underaged son from the Army, and rekindle romance with Wayne. Meanwhile, Tyree (Ben Johnson) is wanted for Manslaughter, and there are several songs from the impressive 'Sons of the Pioneers'.
"Rio Grande" is better than "Fort Apache" and about equal to "She Wore a Yellow Ribbon" in quality. Competently directed, with a fine cast and cinematography, the film is surprisingly sentimental but sometimes drags. As usual in Ford films, the Indians are faceless Savages, with audience sympathy intended for the cavalry soldiers.
Claude Jarman Jr. is well-cast for the role of Wayne's son. He looks the boy his character is supposed to be, and conveys the earnest and determined character traits necessary for the role. The father-son/commander-recruit/ guerilla-war theme was previously used in "Lives of a Bengal Lancer" from 1935, another film in which the son has to perform heroic feats to win the respect of his father.
Trivia: John Wayne's son Patrick makes his film debut. John Ford used "Rio Grande" as a bargaining chip for "The Quiet Man", with Republic Studios willing to gamble on the latter film only if a sure-winner Western was made first. Wayne, O'Hara and McLaglen would star in the superior "The Quiet Man", which turned out to be a hit after all.
<EMAIL_ADDRESS>http://members.tripod.com/~Brian_Koller/movies.html
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Locale (computer software), a set of parameters that defines the user's language, region and any special variant preferences that the user wants to see in their user interface—usually a locale identifier consists of at least a language identifier and a region identifier.


| AbstractCompleteness |
Presence and absence of features, their attributes and their relationships.
|
| AbstractElement |
Type of test applied to the data specified by a data quality scope.
|
| AbstractLogicalConsistency |
Degree of adherence to logical rules of data structure, attribution and relationships.
|
| AbstractPositionalAccuracy |
Accuracy of the position of features.
|
| AbstractResult |
Type of test applied to the data specified by a data quality scope.
|
| AbstractTemporalAccuracy |
Accuracy of the temporal attributes and temporal relationships of features.
|
| AbstractThematicAccuracy |
Accuracy of quantitative attributes and the correctness of non-quantitative attributes
and of the classifications of features and their relationships.
|
| DefaultAbsoluteExternalPositionalAccuracy |
Closeness of reported coordinate values to values accepted as or being true.
|
| DefaultAccuracyOfATimeMeasurement |
Correctness of the temporal references of an item (reporting of error in time measurement).
|
| DefaultCompletenessCommission |
Excess data present in the dataset, as described by the scope.
|
| DefaultCompletenessOmission |
Data absent from the dataset, as described by the scope.
|
| DefaultConceptualConsistency |
Adherence to rules of the conceptual schema.
|
| DefaultConformanceResult |
Information about the outcome of evaluating the obtained value (or set of values) against
a specified acceptable conformance quality level.
|
| DefaultCoverageResult |
Result of a data quality measure organising the measured values as a coverage.
|
| DefaultDataQuality |
Quality information for the data specified by a data quality scope.
|
| DefaultDomainConsistency |
Adherence of values to the value domains.
|
| DefaultFormatConsistency |
Degree to which data is stored in accordance with the physical structure of the dataset, as described by the scope.
|
| DefaultGriddedDataPositionalAccuracy |
Closeness of gridded data position values to values accepted as or being true.
|
| DefaultNonQuantitativeAttributeAccuracy |
Accuracy of non-quantitative attributes.
|
| DefaultQuantitativeAttributeAccuracy |
Accuracy of quantitative attributes.
|
| DefaultQuantitativeResult |
Information about the value (or set of values) obtained from applying a data quality measure.
|
| DefaultRelativeInternalPositionalAccuracy |
Closeness of the relative positions of features in the scope to their respective
relative positions accepted as or being true.
|
| DefaultScope |
Deprecated.
|
| DefaultTemporalConsistency |
Correctness of ordered events or sequences, if reported.
|
| DefaultTemporalValidity |
Validity of data specified by the scope with respect to time.
|
| DefaultThematicClassificationCorrectness |
Comparison of the classes assigned to features or their attributes to a universe of discourse.
|
| DefaultTopologicalConsistency |
Correctness of the explicitly encoded topological characteristics of the dataset as described by the scope.
|
| DefaultUsability |
Deprecated.
|


--- layout: page category: spec title: "Pointer Events Level 2" ---
| Current Status: | Recommendation (REC) |
|---|---|
| Canonical URI: |
http://www.w3.org/TR/pointerevents2
|
| Abstract: | The features in this specification extend or modify those found in "Pointer Events", a W3C Recommendation that describes events and related interfaces for handling hardware agnostic pointer input from devices including a mouse, pen, touchscreen, etc. For compatibility with existing mouse based content, this specification also describes a mapping to fire Mouse Events for other pointer device types. |
Pointer Events Level 2Updates:


Usage guide
This is a guide covering some aspects of using GrapheneOS. See the features page for a list of GrapheneOS features.
Storage access
GrapheneOS inherits the same baseline approach to storage access as modern Android and extends it with our Storage Scopes feature as a fully compatible alternative to standard Android storage permissions. This section provides an overview of the standard approach to storage access primarily to provide context for explaining Storage Scopes.
There are two types of app-accessible storage:
- app-private ("internal") storage:
- inaccessible to other apps
- doesn't require any permission for full access
- cleared when the app is uninstalled
- shared ("external") storage:
- shared with other apps
- access is regulated with permissions
- files persist after uninstallation
For modern apps, access to the shared storage is controlled in the following way:
- Without any storage permission, an app is allowed to:
- create media files in standard directories (audio in Music/, Ringtones/, etc, images in Pictures/ and DCIM/, videos in DCIM/ and Movies/)
- create files of any type (both media and non-media) in Documents/ and Download/
- create new directories inside standard directories
- rename/delete files that were created by the app itself
- rename/delete directories if it can rename/delete all files within those directories
- Media access permission ("Allow access to media only",
READ_EXTERNAL_STORAGE
) allows the app to read media files that were created by other apps. Non-media files remain invisible to it. For apps targeting Android 13, the media access permission is split intoREAD_MEDIA_IMAGES
,READ_MEDIA_VIDEO
andREAD_MEDIA_AUDIO
. - Media management special access permission ("Allow app to manage media",
MANAGE_MEDIA
) allows the app to delete and to rename media files created by other apps. - "All files access" special access permission (
MANAGE_EXTERNAL_STORAGE
) allows the app to read, create, rename and delete files and directories of any type in any directory of the shared storage (including the root directory).
For legacy apps (those that target Android 9 or lower and those that target Android 10 and request legacy storage mode), storage access permissions have a different meaning:
- Without a storage permission, app is not allowed any type of access to any files or directories inside the shared storage.
READ_EXTERNAL_STORAGE
permission allows the app to read both media and non-media files in any directory.WRITE_EXTERNAL_STORAGE
permission allows the app to create, rename and delete files (of any type) and directories in any directory of shared storage (including the root directory).
Additionally, both modern and legacy Android apps can open the system file picker interface to have the user store or load one or more files/directories on their behalf. This type of access doesn't require any of the permissions listed above. Using this approach gives the user control over where files are stored in their home directory and which files/directories can be used by the app. This is based on the Storage Access Framework (SAF) introduced in Android 4.4. SAF allows the user to grant access to files/directories in their home directory, external drives and also app-based storage providers such as network shares, cloud storage, an encrypted volume, an external drive with a filesystem the OS doesn't support for external drives, etc. This is the only way to use those app-based storage providers and modern Android has removed the legacy approach for accessing external drives.
Storage Scopes
GrapheneOS provides the Storage Scopes feature as a fully compatible alternative to the standard Android storage permissions. Storage Scopes can be enabled only if the app doesn't have any storage permission. Enabling Storage Scopes makes the app assume that is has all of storage permissions that were requested by it, despite not actually having any of them.
This means that the app can't see any of the files that were created by other apps. The app is still allowed to create files and directories, same as any other modern app that doesn't have any storage access permission.
Apps that would normally use the legacy storage mode are switched to the modern storage mode when Storage Scopes is enabled.
If the app requests the "All files access" permission (or is a legacy app
that requests WRITE_EXTERNAL_STORAGE
permission), then the write
restrictions that are normally applied to apps that don't have a storage access
permission are relaxed to provide the same write access that the app would have if
it was granted the "All files access" permission.
This is done to ensure compatibility with apps that, for example, create a new
directory in the root of shared storage, or write a text file (eg lyrics.txt) to
the Music/ directory (normally, only audio files can be placed there).
No additional read access is granted to such apps, they still can see only their
own files.
For all other apps, enabling Storage Scopes doesn't grant any additional storage access beyond what a modern app that doesn't have any storage permission already has.
Optionally, users can specify which of the files created by other apps the app can access. Access can be granted to a specific file or to all files in a directory. The standard SAF picker is used for this purpose in a special mode where it shows only shared storage files/directories.
The most significant limitation of Storage Scopes is the fact that the app will lose access to files that it created if it's uninstalled and then installed again, same as any other app that doesn't have a storage access permission. As a workaround, users can manually grant access to these files/directories via SAF picker.
Accessibility
GrapheneOS includes all of the accessibility features from the Android Open Source Project and strives to fill in the gaps from not including Google apps and services. We include our own fork of the open source TalkBack accessibility service along with a Monochromacy option for the standard color correction menu.
GrapheneOS does not yet include a text-to-speech (TTS) service in the base OS due to limitations of the available options. Including one is planned in the future when a suitable option is available. RHVoice and eSpeak NG are both open source and are the most common choices by GrapheneOS users. Both of these work fine but have licensing issues. eSpeak NG has added Direct Boot based on our request for it, meaning it is able to function before the first unlock. RHVoice is missing Direct Boot and can't run before the first unlock. Installing and setting up either one of these or another TTS app will get TalkBack working. TalkBack itself supports Direct Boot and works before the first unlock but it needs to have a TTS app supporting it in order to do more than playing the activation sound before the first unlock. After installing a TTS service, you need to select it in the OS configuration to accept activating it. The OS will display one of them as already selected, but it won't simply work from being installed as that wouldn't be safe. This is the same as the stock OS but it comes with one set up already.
GrapheneOS disables showing the characters as passwords are typed by default. You can enable this in Settings ➔ Privacy.
Third party accessibility services can be installed and activated. This includes the ones made by Google. Most of these will work but some may have a hard dependency on functionality from Google Play services for some of their functionality or to run at all. Accessibility services are very powerful and we strongly recommend against using third party implementations if you can get by well without them. We plan to add safeguards in this area while still keeping them working without problematic barriers.
Auditor
See the tutorial page on the site for the attestation sub-project.
Updates
The update system implements automatic background updates. It checks for updates approximately once every four hours when there's network connectivity and then downloads and installs updates in the background. It will pick up where it left off if downloads are interrupted, so you don't need to worry about interrupting it. Similarly, interrupting the installation isn't a risk because updates are installed to a secondary installation of GrapheneOS which only becomes the active installation after the update is complete. Once the update is complete, you'll be informed with a notification and simply need to reboot with the button in the notification or via a normal reboot. If the new version fails to boot, the OS will be rolled back to the past version and the updater will attempt to download and install the update again.
The updater will use incremental (delta) updates to download only changes rather than the whole OS when one is available to go directly from the installed version to the latest version. As long as you have working network connectivity on a regular basis and reboot when asked, you'll almost always be on one of the past couple versions of the OS which will minimize bandwidth usage since incrementals will always be available.
The updater works while the device is locked / idle, including before the first unlock since it's explicitly designed to be able to run before decryption of user data.
Release changelogs are available in a section on the releases page.
Settings
The settings are available in the Settings app in System ➔ System update.
The "Check for updates" option will manually trigger an update check as soon as possible. It will still wait for the configuration conditions listed below to be satisfied, such as being connected to the internet via one of the permitted network types.
The "Release channel" setting can be changed from the default Stable channel to the Beta channel if you want to help with testing. The Beta channel will usually simply follow the Stable channel, but the Beta channel may be used to experiment with new features.
The "Permitted networks" setting controls which networks will be used to perform updates. It defaults to using any network connection. It can be set to "Non-roaming" to disable it when the cellular service is marked as roaming or "Unmetered" to disable it on cellular networks and also Wi-Fi networks marked as metered.
The "Require battery above warning level" setting controls whether updates will only be performed when the battery is above the level where the warning message is shown. The standard value is at 15% capacity.
Enabling the opt-in "Automatic reboot" setting allows the updater to reboot the device after an update once it has been idle for a long time. When this setting is enabled, a device can take care of any number of updates completely automatically even if it's left completely idle.
The "Notification settings" option is a shortcut to the System Updater notification settings which allows you to control notification settings from System Updater such as notification dot, lock screen, and noisy / silent notifications. These notifications include updater errors, progress, already up to date, and reboot prompts. By default all notifications are enabled.
Security
The update server isn't a trusted party since updates are signed and verified along with downgrade attacks being prevented. The update protocol doesn't send identifiable information to the update server and works well over a VPN / Tor. GrapheneOS isn't able to comply with a government order to build, sign and ship a malicious update to a specific user's device based on information like the IMEI, serial number, etc. The update server only ends up knowing the IP address used to connect to it and the version being upgraded from based on the requested incremental.
Android updates can support serialno constraints to make them validate only on a certain device but GrapheneOS rejects any update with a serialno constraint for both over-the-air updates (Updater app) and sideloaded updates (recovery).
Disabling
It's highly recommended to leave automatic updates enabled and to configure the permitted networks if the bandwidth usage is a problem on your mobile data connection. However, it's possible to turn off the update client by going to Settings ➔ Apps, enabling Show system via the menu, selecting System Updater and disabling the app. If you do this, you'll need to remember to enable it again to start receiving updates.
Sideloading
Updates can be downloaded via the releases page and installed via recovery with adb sideloading. The zip files are signed and verified by recovery, just as they are by the update client within the OS. This includes providing downgrade protection, which prevents attempting to downgrade the version. If recovery didn't enforce these things, they would still be enforced via verified boot including downgrade protection and the attempted update would just fail to boot and be rolled back.
To install one by sideloading, first, boot into recovery. You may do this either by
using adb reboot recovery
from the operating system, or by selecting the
"Recovery" option in the bootloader interface.
You should see the green Android lying on its back being repaired, with the text "No command" meaning that no command has been passed to recovery.
Next, access the recovery menu by holding down the power button and pressing the volume up button a single time. This key combination toggles between the GUI and text-based mode with the menu and log output.
Finally, select the "Apply update from ADB" option in the recovery menu and sideload the update with adb. For example:
adb sideload raven-ota_update-2021122018.zip
You do not need to have adb enabled within the OS or the host's ADB key whitelisted within the OS to sideload an update to recovery. Recovery mode does not trust the attached computer and this can be considered a production feature. Trusting a computer with ADB access within the OS is much different and exposes the device to a huge amount of attack surface and control by the trusted computer.
USB peripherals
GrapheneOS defaults to ignoring connected USB peripherals when the device is already booted and the screen is locked. A USB device already connected at boot will still work. The purpose is reducing attack surface for a locked device with active login sessions to user profiles to protect data that's not at rest. This can be controlled in Settings ➔ Security ➔ USB accessories. The options are:
- Disallow new USB peripherals
- Allow new USB peripherals when unlocked (default)
- Allow new USB peripherals (like stock Android)
This option has no impact on the device acting as a USB peripheral itself when connected to a computer. Android defaults to charge only mode and requires opt-in to the device being used for file transfer, USB tethering, MIDI or PTP.
Web browsing
GrapheneOS includes our Vanadium subproject providing privacy and security enhanced releases of Chromium. Vanadium is both the user-facing browser included in the OS and the provider of the WebView used by other apps to render web content. The WebView is the browser engine used by nearly all other apps embedding web content or using web technologies for other uses. It's also used by many minor web browsers not forking Chromium as a whole. These apps using the WebView benefit from a subset of the Vanadium hardening.
Vanadium was previously primarily focused on security hardening but we plan on adding assorted privacy and usability features. In the near future, we plan to add support for always incognito mode, content filtering (ad blocking, etc.), improved state partitioning, backup/restore and many other features.
Chromium-based browsers like Vanadium provide the strongest sandbox implementation, leagues ahead of the alternatives. It is much harder to escape from the sandbox and it provides much more than acting as a barrier to compromising the rest of the OS. Site isolation enforces security boundaries around each site using the sandbox by placing each site into an isolated sandbox. It required a huge overhaul of the browser since it has to enforce these rules on all the IPC APIs. Site isolation is important even without a compromise, due to side channels. Browsers without site isolation are very vulnerable to attacks like Spectre. On mobile, due to the lack of memory available to apps, there are different modes for site isolation. Vanadium turns on strict site isolation, matching Chromium on the desktop, along with strict origin isolation.
Chromium has decent exploit mitigations, unlike the available alternatives. This is improved upon in Vanadium by enabling further mitigations, including those developed upstream but not yet fully enabled due to code size, memory usage or performance. For example, it enables type-based CFI like Chromium on the desktop, uses a stronger SSP configuration, zero initializes variables by default, etc. Some of the mitigations are inherited from the OS itself, which also applies to other browsers, at least if they don't do things to break them.
We recommend against trying to achieve browser privacy and security through piling on browser extensions and modifications. Most privacy features for browsers are privacy theater without a clear threat model and these features often reduce privacy by aiding fingerprinting and adding more state shared between sites. Every change you make results in you standing out from the crowd and generally provides more ways to track you. Enumerating badness via content filtering is not a viable approach to achieving decent privacy, just as AntiVirus isn't a viable way to achieving decent security. These are losing battles, and are at best a stopgap reducing exposure while waiting for real privacy and security features.
Vanadium will be following the school of thought where hiding the IP address through Tor or a trusted VPN shared between many users is the essential baseline, with the browser partitioning state based on site and mitigating fingerprinting to avoid that being trivially bypassed. The Tor Browser's approach is the only one with any real potential, however flawed the current implementation may be. This work is currently in a very early stage and it is largely being implemented upstream with the strongest available implementation of state partitioning. Chromium is using Network Isolation Keys to divide up connection pools, caches and other state based on site and this will be the foundation for privacy. Chromium itself aims to prevent tracking through mechanisms other than cookies, greatly narrowing the scope downstream work needs to cover. The focus is currently on research since we don't see much benefit in deploying bits and pieces of this before everything is ready to come together. At the moment, the only browser with any semblance of privacy is the Tor Browser but there are many ways to bypass the anti-fingerprinting and state partitioning. The Tor Browser's security is weak which makes the privacy protection weak. The need to avoid diversity (fingerprinting) creates a monoculture for the most interesting targets. This needs to change, especially since Tor itself makes people into much more of a target (both locally and by the exit nodes).
WebView-based browsers use the hardened Vanadium rendering engine, but they can't offer as much privacy and control due to being limited to the capabilities supported by the WebView widget. For example, they can't provide a setting for toggling sensors access because the feature is fairly new and the WebView WebSettings API doesn't yet include support for it as it does for JavaScript, location, cookies, DOM storage and other older features. For sensors, the Sensors app permission added by GrapheneOS can be toggled off for the browser app as a whole instead. The WebView sandbox also currently runs every instance within the same sandbox and doesn't support site isolation.
Avoid Gecko-based browsers like Firefox as they're currently much more vulnerable
to exploitation and inherently add a huge amount of attack surface. Gecko doesn't have
a WebView implementation (GeckoView is not a WebView implementation), so it has to be
used alongside the Chromium-based WebView rather than instead of Chromium, which means
having the remote attack surface of two separate browser engines instead of only one.
Firefox / Gecko also bypass or cripple a fair bit of the upstream and GrapheneOS
hardening work for apps. Worst of all, Firefox does not have internal sandboxing
on Android. This is despite the fact that Chromium semantic sandbox layer on
Android is implemented via the OS isolatedProcess
feature, which is a
very easy to use boolean property for app service processes to provide strong
isolation with only the ability to communicate with the app running them via the
standard service API. Even in the desktop version, Firefox's sandbox is still
substantially weaker (especially on Linux) and lacks full support for isolating
sites from each other rather than only containing content as a whole. The sandbox
has been gradually improving on the desktop but it isn't happening for their
Android browser yet.
Camera
GrapheneOS has the same camera capabilities and quality as the stock OS. It will match the stock OS when comparing the same app on each OS. GrapheneOS uses our own modern Camera app rather than the standard AOSP Camera app. GrapheneOS Camera is far better than any of the portable open source camera alternatives and even most proprietary camera apps including paid apps. On Pixels, Google Camera can be used as an alternative with more features. The section below has a detailed guide on using GrapheneOS Camera and the following section explains the remaining advantages of Google Camera on Pixels.
GrapheneOS Camera app
GrapheneOS includes our own modern camera app focused on privacy and security. It includes modes for capturing images, videos and QR / barcode scanning along with additional modes based on CameraX vendor extensions (Portrait, HDR, Night, Face Retouch and Auto) on devices where they're available (not available on Pixels yet).
Modes are displayed as tabs at the bottom of the screen. You can switch between modes using the tab interface or by swiping left/right anywhere on the screen. The arrow button at the top of the screen opens the settings panel and you can close it by pressing anywhere outside the settings panel. You can also swipe down to open the settings and swipe up to close it. Outside of the QR scanning mode, there's a row of large buttons above the tab bar for switching between the cameras (left), capturing images and starting/stopping video recording (middle) and opening the gallery (right). The volume keys can also be used as an equivalent to pressing the capture button. While recording a video, the gallery button becomes an image capture button for capturing images.
Our Camera app provides the system media intents used by other apps to capture images / record videos via the OS provided camera implementation. These intents can only be provided by a system app since Android 11, so the quality of the system camera is quite important.
The app has an in-app gallery and video player for images/videos taken with it. It currently opens an external editor activity for the edit action. GrapheneOS comes with AOSP Gallery which provides an editor activity. You can install a nicer photo editor and the Camera app will be able to use it. We plan to replace AOSP Gallery with a standalone variant of the gallery we're developing for the Camera app in the future.
Using the default 4:3 aspect ratio for image capture is recommended since 16:9 is simply cropped output on all supported devices. A device oriented towards video recording might actually have a wider image sensor but that's not the case for Pixels or nearly any other smartphone.
Image capture uses lightweight HDR+ on all supported Pixels and HDRnet for the preview on 5th generation Pixels. Using the torch or camera flash will result in HDR+ being disabled which is why automatic flash isn't enabled by default. The lightweight HDR+ doesn't use as many frames as the more aggressive Google Camera HDR+. CameraX extensions will eventually provide support for an HDR mode with more aggressive HDR+ taking/combining more than only around 3 frames along with a Night mode providing the Night Sight variant of HDR+ inflating the light of the scene through combining the frames. Other fancy features like Portrait mode will also depend on CameraX extensions being provided in the future. There isn't a timeline for this but an initial implementation will likely be shipped within the next year for Pixels.
Zooming via pinch to zoom or the zoom slider will automatically make use of the wide angle and telephoto cameras on Pixels. 5th and 6th generation Pixels (4a (5G), 5, 5a, 6, 6 Pro) have a wide angle camera for zooming out to under 1x to capture a much wider field of view. Images taken with the wide angle lens won't match the quality of the normal camera, especially with 6th generation Pixels. Flagship 4th generation Pixels (4, 4 XL) have a telephoto camera providing 2x optical zoom and the Pixel 6 Pro has one providing 4x optical zoom.
By default, continuous auto focus, auto exposure and auto white balance are used across the whole scene. Tapping to focus will switch to auto focus, auto exposure and auto white balance based on that location. The focus timeout setting determines the timeout before it switches back the default mode. The exposure compensation slider on the left allows manually tuning exposure and will automatically adjust shutter speed, aperture and ISO without disrupting lightweight HDR+ support. Further configuration / tuning will be provided in the future.
The QR scanning mode only scans within the scanning square marked on the screen. The QR code should be aligned with the edges of the square but can have any 90 degree orientation. Non-standard inverted QR codes are fully supported. It's a very quick and high quality QR scanner able to easily scan very high density QR codes from Pixels.  It has full support for zooming in and out. The torch can be toggled with the button at the bottom center. The auto toggle at the bottom left can be used to toggle scanning for all supported barcode types. Alternatively, you can select which barcode types it should scan via the menu at the top. It only scans QR codes by default since that provides quick and reliable scanning. Most other types of barcodes can result in false positives. Each enabled type will slow down the scanning and will make it more prone to false positives especially with difficult to scan barcodes such as a dense QR code.
Camera permission is the only one that's required. Images and videos are stored via the Media Store API so media/storage permissions aren't required. The Microphone permission is needed for video recording by default but not when including audio is disabled. Location permission is only needed if you explicitly enabling location tagging, which is an experimental feature.
By default, EXIF metadata is stripped for captured images and only includes the orientation. Stripping metadata for videos is planned but not supported yet. Orientation metadata isn't stripped since it's fully visible from how the image is displayed so it doesn't count as hidden metadata and is needed for proper display. You can toggle off stripping EXIF metadata in the More Settings menu opened from the settings dialog. Disabling metadata stripping will leave the timestamp, phone model, exposure configuration and other metadata. Location tagging is disabled by default and won't be stripped if you enable it.
Electronic Image Stabilization (EIS) is enabled by default on devices providing it via the Camera2 API and can be disabled using the video settings dialog.
Zero Shutter Lag (ZSL) is available as an opt-in toggle in More Settings and speeds up image capture for the Camera mode when flash is disabled.
Google Camera
Google Camera can take full advantage of the available cameras and image processing hardware as it can on the stock OS and does not require GSF or sandboxed Google Play on GrapheneOS. Direct TPU and GXP access by Google apps including Google Camera is controlled by a toggle added by GrapheneOS and doesn't provide them with any additional access to data. The toggle exists for attack surface reduction. Every app can use the TPU and GXP via standard APIs including the Android Neural Networks API and Camera2 API regardless.
We aim to reduce the benefits of Google Camera compared to GrapheneOS Camera over time, especially on Pixels. Many features of Google Camera will end up being available for GrapheneOS Camera in the next year or so via CameraX extensions including more aggressive HDR+, Night Sight and Portrait. Video features such as slow motion and time lapse are likely further away than within the next year. These video features could potentially be provided via CameraX vendor extensions or could be implemented via our own post-processing of the video output. Panorama, Photo Sphere, Astrophotography, Motion Photos, Frequent Faces, Dual Exposure Controls, Google Lens, etc. aren't on the roadmap for GrapheneOS Camera. Video frame rate configuration and H.265 support should be available for GrapheneOS Camera in the near future via CameraX improvements along with DNG (RAW) support in the further future.
Exec spawning
GrapheneOS creates fresh processes (via exec) when spawning applications instead of using the traditional Zygote spawning model. This improves privacy and security at the expense of higher cold start app spawning time and higher initial memory usage. It doesn't impact runtime performance beyond the initial spawning time. It adds somewhere in the ballpark of 200ms to app spawning time on the flagship devices and is only very noticeable on lower-end devices with a weaker CPU and slower storage. The spawning time impact only applies when the app doesn't already have an app process and the OS will try to keep app processes cached in the background until memory pressure forces it to start killing them.
In the typical Zygote model, a template app process is created during boot and every app is spawned as a clone of it. This results in every app sharing the same initial memory content and layout, including sharing secrets that are meant to be randomized for each process. It saves time by reusing the initialization work. The initial memory usage is reduced due to copy-on-write semantics resulting in memory written only during initialization being shared between app processes.
The Zygote model weakens the security provided by features based on random secrets including Address Space Layout Randomization (ASLR), stack canaries, heap canaries, randomized heap layout and memory tags. It cripples these security features since every app has the values for every other app and the values don't change for fresh app processes until reboot. Much of the OS itself is implemented via non-user-facing apps with privileges reserved for OS components. The Zygote template is reused across user profiles, so it also provides a temporary set of device identifiers across profiles for each boot via the shared randomized values.
This feature can be disabled via Settings ➔ Security ➔ Enable secure app spawning if you prefer to have faster cold start app spawning time and lower app process memory usage instead of the substantial security benefits and the removal of the only known remaining direct device identifiers across profiles (i.e. not depending on fingerprinting global configuration, available storage space, etc. or using side channels).
Bugs uncovered by security features
GrapheneOS substantially expands the standard mitigations for memory corruption vulnerabilities. Some of these features are designed to directly catch the memory corruption bugs either via an explicit check or memory protection and abort the program in order to prevent them from being exploited. Other features mitigate issues a bit less directly such as zeroing data immediately upon free, isolated memory regions, heap randomization, etc. and can also lead to latent memory corruption bugs crashing instead of the program continuing onwards with corrupted memory. This means that many latent memory corruption bugs in apps are caught along with some in the OS itself. These bugs are not caused by GrapheneOS, but rather already existed and are uncovered by the features. The features are aimed at preventing or hindering exploits, not finding bugs, but they do that as part of doing their actual job.
Similarly, some of the other privacy and security improvements reduce the access available to applications and they may crash. Some of these features are always enabled under the hood, while others like the Network and Sensors toggles are controlled by users via opt-in or opt-out toggles. Apps may not handle having access taken away like this, although it generally doesn't cause any issues as it's all designed to be friendly to apps and fully compatible rather than killing the application when it violates the rules.
You can enable our exploit protection compatibility mode via Settings ➔ Apps ➔ App ➔ Advanced. The exploit protection compatibility mode toggle will switch from hardened_malloc to Android's standard allocator (Scudo) and will reduce address space size from 48 bit to Android's standard 39 bit. There are also separate toggles for these features in the Configure hardening menu if you want to narrow down the cause to a specific feature.
If you run into an application aborting, try to come up with a process for reproducing the issue and then capture a bug report via the 'Take bug report' feature in Developer options. Report an issue to the GrapheneOS OS issue tracker and email the bug report capture zip to<EMAIL_ADDRESS>with the issue tracker number in the subject like "Bug report capture for issue #104". The bug report capture includes plain text 'tombstones' with logs, tracebacks, address space layout, register content and a tiny bit of context from memory from areas that are interesting for debugging. This may contain some sensitive data. Feel free to provide only the tombstone for the relevant crash and filter out information you don't want to send. However, it will be more difficult to debug if you provide less of the information. If the app doesn't work with sensitive information, just send the whole tombstone.
Wi-Fi privacy
Wi-Fi on GrapheneOS is very privacy-friendly and is essentially anonymous as long as apps do not leak uniquely identifying information to the network. GrapheneOS avoids allowing itself to be fingerprinted as GrapheneOS, other than connections which are documented (see the default connections FAQ) and can be easily disabled or forced through a VPN service.
Scanning
MAC randomization is always performed for Wi-Fi scanning. Pixel phones have firmware support for scanning MAC randomization going significantly beyond a naive implementation. On many other devices, there are identifiers exposed by Wi-Fi scanning beyond the MAC address such as the packet sequence number and assorted identifying information in the probe requests.
Avoid using hidden APs (i.e. APs not broadcasting their SSID) since all known hidden SSIDs end up being broadcast as part of scanning for networks to find them again. SSIDs are not broadcast for standard non-hidden APs. Hidden APs are only hidden when no devices are connected. It makes little sense as a privacy feature, especially for a non-mobile AP where knowing the AP exists can't be used for tracking it since it doesn't move. The feature reduces your privacy rather than increasing it. If you need to use a hidden AP, make sure to delete the saved network afterwards.
Wi-Fi and Bluetooth scanning for improving location detection are disabled by default, unlike the stock OS. These can be toggled in Settings ➔ Location ➔ Location Services ➔ Wi-Fi and Bluetooth scanning. These features enable scanning even when Wi-Fi or Bluetooth is disabled, so these need to be kept disabled to fully disable the radios when Wi-Fi and Bluetooth are disabled. GrapheneOS itself doesn't currently include a supplementary location service based on Wi-Fi and Bluetooth scanning. These options impact whether apps such as sandboxed Google Play are able to use the functionality if you grant them the Location permission. GrapheneOS plans to eventually include an OS service based on local databases rather than a network-based service giving the user's location to a server whenever location is being used.
Associated with an Access Point (AP)
Associated MAC randomization is performed by default. This can be controlled per-network in Settings ➔ Network & Internet ➔ Internet ➔ <network> ➔ Privacy.
In the stock OS, the default is to use a unique persistent random MAC address for each network. It has 2 options available: "Use randomized MAC (default)" and "Use device MAC". In GrapheneOS, the default is generating a new random MAC address when connecting to a network. It has 3 options available: "Use per-connection randomized MAC (default)", "Use per-network randomized MAC" and "Use device MAC".
In rare cases, broken routers are unable to accept new clients once their DHCP table is full instead of clearing the last recently used entry. You can work around this by manually clearing the DHCP table via the router administration page and can switch to the per-network randomized MAC mode to avoid triggering the issue again. This would prevent a router being used in any situation where many clients naturally come and go even without per-connection MAC randomization and is not generally an issue for any modern routers. Per-connection MAC randomization only makes it more likely to find a one of the rare routers with this issue.
The DHCP client uses the anonymity profile rather than sending a hostname so it doesn't compromise the privacy offered by MAC randomization. When the per-connection MAC randomization added by GrapheneOS is being used, DHCP client state is flushed before reconnecting to a network to avoid revealing that it's likely the same device as before.
GrapheneOS also disables support for stable link-local IPv6 addresses, since these have the potential to be used as identifiers. It's more sensible to use typical link-local address generation based on the (randomized) MAC address since link-local devices have access to both. As of Android 11, Android only uses stable link-local privacy addresses when MAC randomization is disabled, so we no longer need to disable the feature.
LTE-only mode
If you have a reliable LTE connection from your carrier, you can reduce attack surface by disabling 2G, 3G and 5G connectivity in Settings ➔ Network & Internet ➔ SIMs ➔ Preferred network type. Traditional voice calls will only work in the LTE-only mode if you have either an LTE connection and VoLTE (Voice over LTE) support or a Wi-Fi connection and VoWi-Fi (Voice over Wi-Fi) support. VoLTE / VoWi-Fi works on GrapheneOS for most carriers unless they restrict it to carrier phones. Some carriers may be missing VoWi-Fi due to us not including their proprietary apps. Please note that AT&T users may see "5Ge" being used when LTE Only mode is enabled as AT&T intentionally mislabel LTE services as "5Ge" to mislead users.
This feature is not intended to improve the confidentiality of traditional calls and texts, but it might somewhat raise the bar for some forms of interception. It's not a substitute for end-to-end encrypted calls / texts or even transport layer encryption. LTE does provide basic network authentication / encryption, but it's for the network itself. The intention of the LTE-only feature is only hardening against remote exploitation by disabling an enormous amount of both legacy code (2G, 3G) and bleeding edge code (5G).
Sandboxed Google Play
GrapheneOS has a compatibility layer providing the option to install and use the official releases of Google Play in the standard app sandbox. Google Play receives absolutely no special access or privileges on GrapheneOS as opposed to bypassing the app sandbox and receiving a massive amount of highly privileged access. Instead, the compatibility layer teaches it how to work within the full app sandbox. It also isn't used as a backend for the OS services as it would be elsewhere since GrapheneOS doesn't use Google Play even when it's installed.
Since the Google Play apps are simply regular apps on GrapheneOS, you install them within a specific user or work profile and they're only available within that profile. Only apps within the same profile can use it and they need to explicitly choose to use it. It works the same way as any other app and has no special capabilities. As with any other app, it can't access data of other apps and requires explicit user consent to gain access to profile data or the standard permissions. Apps within the same profile can communicate with mutual consent and it's no different for sandboxed Google Play.
Sandboxed Google Play is close to being fully functional and provides near complete compatibility with the app ecosystem depending on Google Play. Only a small subset of privileged functionality which we haven't yet ported to different approaches with our compatibility layer is unavailable. Some functionality is inherently privileged and can't be provided as part of the compatibility layer.
The vast majority of Play services functionality works perfectly including dynamically downloaded / updated modules (dynamite modules) and functionality provided by modular app components such as Google Play Games. By default, location requests are rerouted to a reimplementation of the Play geolocation service provided by GrapheneOS. You can disable rerouting and use the standard Play services geolocation service instead if you want the Google network location service and related features.
Our compatibility layer includes full support for the Play Store. Play Store services are fully available including in-app purchases, Play Asset Delivery, Play Feature Delivery and app / content license checks. It can install, update and uninstall apps with the standard approach requiring that the user authorizes it as an app source and consents to each action. It will use the standard Android 12+ unattended update feature to do automatic updates for apps where it was the last installer.
Installation
The simplest approach is to only use the Owner user profile. Apps installed in the Owner profile are sandboxed the same way as everywhere else and don't receive any special access. If you want to choose which apps use Google Play rather than making it available to all of them, install it in a separate user or work profile for apps depending on Google Play. You could also do it the other way around, but it makes more sense to try to use as much as possible without Google Play rather than treating not using it as the exceptional case.
Google Play is divided up into 3 separate apps:
- Google Services Framework (GSF)
- Google Play services
- Google Play Store
To use sandboxed Google Play, you simply need to install the official releases of these 3 apps in the user and work profiles where you want to use it. Open our app repository client (look for Apps in the app drawer) and install the 3 core Google Play apps mirrored in our repository. Our app repository client has support for dependency installation so you can simply directly install Play services and it will install GSF and the Play Store as dependencies.
Play services and the Play Store depend on each other, one will not work properly without the other. Both of them depend on the Google Services Framework app. Our app repository handles this automatically.
You can obtain updates to these apps from our app repository client or from the Play Store. Updates through the Play Store usually arrive first.
You should give a battery optimization exception to Google Play services for features like push notifications to work properly in the background. It isn't needed for the other 2 apps.
Signing in into a Google account is optional, unless you want to use features depending on being signed into an account. For example, some apps use Google account authentication instead of their accounts having a username and password. The Play Store requires being signed into an account in order to install apps or use in-app purchases. This is still true even for an alternate frontend to the Play Store. Aurora Store still requires an account but fetches shared account credentials from Aurora Store's service by default.
The Play Store provides many services used by apps including Play Asset Delivery, Play Feature Delivery, in-app purchases and license checks for paid apps. The Play Store app is also the most secure way to install and update apps from the Play Store.
Our compatibility layer has support for Play Games Services which you can obtain by installing Google Play Games from the Play Store. Many games on the Play Store depend on having Google Play Games installed.
Some apps may work with only GSF installed, without Play services and the Play Store.
Configuration
The compatibility layer has a configuration menu available at Settings ➔ Apps ➔ Sandboxed Google Play.
By default, apps using Google Play geolocation are redirected to our own implementation on top of the standard OS geolocation service. If you want to use Google's geolocation service instead, you can disable the "Reroute location requests to OS APIs" toggle and manually grant "Allow all the time" Location access to Google Play services. For it to be fully functional, you also need to use "Google Location Accuracy" link to access the Google Play services menu for opting into their network location service. This will send the nearby Wi-Fi and cellular networks provided via the Location permission to their service to retrieve a location estimate. The Nearby Devices permission can also be granted to give it access to nearby Bluetooth device IDs. If you stick with the default enabled redirection mode, none of this needs to be granted for working geolocation in apps. In order to fully take advantage of Wi-Fi and Bluetooth scanning, you also need to enable the scanning toggles in Settings ➔ Location ➔ Location services which are disabled by default rather than enabled by default like the stock OS.
Re-routing location to the OS geolocation service will use more power than using the Google Play geolocation service since we do not provide a network-based location service and implement it via GNSS / A-GPS only. In the future, we plan on providing a pseudo-network geolocation service for the OS by using a local database of cell towers, and the location redirection feature can also make use of this future OS implementation for network location requests once it's available.
The Google Location Accuracy and Google settings activities would normally be integrated into the OS but we don't include any of the standard Google Play integration so there needs to be an app providing a way to access them.
The menu also provides links to this usage guide, Play services system settings, Play Store system settings and Google settings. The Play services and Play Store system settings are only included for convenience since they can be accessed the same way as any other app via Settings ➔ Apps.
Limitations
Our compatibility layer has to be expanded on a case-by-case basis to teach Play services to work as a regular app without any of the invasive access and integration it expects. In many cases, it doesn't truly need the access or we can teach it to use the regular approach available to a normal app. In some cases, the functionality it offers fundamentally requires privileged access and cannot be supported. For example, it's unlikely Android Auto will be supported. The same applies to other highly invasive OS integration / control or privileged access to hardware. Our compatibility layer is a very actively developed work in progress and most of the remaining unavailable functionality is quickly becoming supported. In the future, we can also support redirection for more APIs such as FIDO2 rather than only the geolocation service.
Functionality depending on the OS integrating Play services and using it as a backend is unavailable. An OS integrating Play uses it as the backend for OS services such as geolocation. GrapheneOS never uses it as the backend/provider for OS services. In cases such as text-to-speech (TTS) where the OS allows the user to choose the provider, Play services can often be used. It's on a level playing field with other apps on GrapheneOS.
Privileged eSIM management
By default GrapheneOS always has shipped with baseline support for eSIM, where users can use any eSIMs installed previously on the device. However, in order to manage and add eSIMs, proprietary Google functionality is needed. This is fully disabled by default.
Privileged eSIM management can be enabled in Settings ➔ Network & Internet ➔ Privileged eSIM management. The toggle will be greyed out and unusable if sandboxed Google Play is not installed, as the functionality is reliant on it.
By enabling the toggle, the proprietary Google functionality is enabled and will be used by the OS to provision and manage eSIMs.
Note that if the eSIM installation process does not progress past the
"Checking network info..." stage despite having a stable Internet connection,
you may need to call the USSD code *#*#4636#*#*
and then enable
DSDS in the menu that is presented.
Banking apps
Banking apps are a particularly problematic class of apps for compatibility with alternate operating systems. Some of these work fine with any GrapheneOS configuration but most of them have extensive dependencies on Play services. For many of these apps, it's enough to set up the GrapheneOS sandboxed Google Play feature in the same profile. Unfortunately, there are further complications not generally encountered with non-financial apps.
Many of these apps have their own crude anti-tampering mechanisms trying to prevent inspecting or modifying the app in a weak attempt to hide their code and API from security researchers. GrapheneOS allows users to disable native code debugging via a toggle in Settings ➔ Security to improve the app sandbox and this can interfere with apps debugging their own code to add a barrier to analyzing the app. You should try enabling this again if you've disabled it and are encountering compatibility issues with these kinds of apps.
Banking apps are increasingly using Google's SafetyNet attestation service to
check the integrity and certification status of the operating system. GrapheneOS
passes the basicIntegrity
check but isn't certified by Google so it
fails the ctsProfileMatch
check. Most apps currently only enforce
weak software-based attestation which can be bypassed by spoofing what it checks.
GrapheneOS doesn't attempt to bypass the checks since it would be very fragile and
would repeatedly break as the checks are improved. Devices launched with Android 8
or later have hardware attestation support which cannot be bypassed without leaked
keys or serious vulnerabilities so the era of being able to bypass these checks by
spoofing results is coming to an end regardless.
The hardware attestation feature is part of the Android Open Source Project and is fully supported by GrapheneOS. SafetyNet attestation chooses to use it to enforce using Google certified operating systems. However, app developers can use it directly and permit other properly signed operating systems upholding the security model. GrapheneOS has a detailed guide for app developers on how to support GrapheneOS with the hardware attestation API. Direct use of the hardware attestation API provides much higher assurance than using SafetyNet so these apps have nothing to lose by using a more meaningful API and supporting a more secure OS.
A 3rd party community-sourced effort containing banking app compatibility information is maintained by PrivSec.dev. GrapheneOS does not make any guarantees regarding the list's validity.
App link verification
Android apps can declare associations with domains in order to handle those
URLs in the app automatically. For security reasons, app links are disabled by
default to prevent apps intercepting arbitrary URLs. First party apps associated
with a domain are expected to be authorized by the domain. Apps can ask for their
app links to be verified by the OS by marking them with autoVerify
in
their manifest. The OS will securely confirm that the domain authorizes the app to
handle the domain's URLs. Users can also manually enable an app's link
associations via Settings ➔ Apps ➔ App name ➔ Open by default ➔ Add link. Apps can
ask users to enable the associations and send them to this page in the Settings
app.
As an example, the first party YouTube app will have the app links verified by the OS automatically while the NewPipe app requires manually enabling handling links for YouTube and other sites.
Verification of app links by the OS is done by the Intent Filter Verification
Service system app. It will use an HTTPS GET request to fetch
https://example.com/.well-known/assetlinks.json
in order to process a
request to verify that an app can handle example.com
links. The app
needs to have their app id and signing keys authorized by the domain in order for
the verification to succeed.
These network requests by the Intent Filter Verification Service to verify app associations with domains are commonly confused for network requests made by the apps. It's simply an HTTPS GET request without identifying information and doesn't offer a communication channel with the app. Redirects won't be followed so there will be a single request for each attempt to verify a domain.
If you don't want automatic app link verification, you can disable the Network permission added by GrapheneOS for the Intent Filter Verification Service system app. In the future, we may provide a way to disable verification directly instead of stopping it from working. It will make heavily throttled attempts to verify a domain after the check failed which won't negatively impact battery life due to the conservative JobScheduler-based implementation.
For more details, see the developer documentation on app link verification.
Carrier functionality
GrapheneOS aims to work with all carriers that are officially supported by Google on the stock operating system on Pixel devices. Wi-Fi Calling, VoLTE, Visual Voicemail, MMS, SMS, Calling and 5G (SA and NSA) all are supported, however some functionality may not be usable due to Google not supporting carriers on the stock OS officially or due to GrapheneOS not shipping proprietary apps required in order for this functionality to work on some carriers. GrapheneOS extracts CarrierConfigs, APNs, modem configurations, Visual Voicemail configurations and MMS configurations from the stock operating system to ensure users get easy carrier support that "just works".
Please note that in some regions, LTE is referred to as 4G.
Generally 5G, SMS, MMS, Calls and VoLTE will work fine on GrapheneOS with officially supported carriers by Google. Wi-Fi calling may vary due to a reliance on proprietary Google apps which GrapheneOS does not ship.
If you are having issues with Visual Voicemail, please be aware that AT&T USA users are unable to use this feature currently due to a lack of AOSP support. Other carriers are done on a best effort basis. We would suggest using Google Dialer with sandboxed Google Play if you are unable to get this feature working.
If you are having problems sending or receiving SMS/MMS messages, we suggest that you perform the following steps:
- Deregister your phone number from Apple iMessage
- Deregister your phone number from Google Chat Features
- Deregister your phone number from your carrier's RCS service (Not all carriers have this)
If you continue to have problems despite following the instructions above or you have another carrier related issue, we suggest that you perform the following steps:
- Some carriers require you to explicitly opt in to use services such as Wi-Fi calling. Consult your carrier's documentation on the process for this or contact them.
- Reset Mobile Network settings in Settings ➔ System ➔ Reset options ➔ Reset Wi-Fi, mobile & Bluetooth and then reboot the device.
- USA users only: You may need to request your carrier to enable CDMA-less mode if you have issues.
- Follow your carrier's instructions for setting up APNs, this can be found in Settings ➔ Network & Internet ➔ SIMs ➔ Access Point Names
- If calls do not work and you have LTE-only mode enabled, try toggling it off. If "Allow 2G" is disabled, try toggling it back on. Your carrier may not properly support VoLTE.
- As a last resort you may need to ask your carrier for a replacement SIM card.
Some carriers may restrict functionality, such as VoLTE, on imported Pixel devices as they only whitelist the IMEI ranges of Pixel device SKUs which were sold locally. You can check your SKU on GrapheneOS by going to Settings ➔ About phone ➔ Model ➔ Hardware SKU and using the official Google documentation. You should check if such functionality works on the stock OS to troubleshoot. It is not possible to change the IMEI on a production device and GrapheneOS will never add support for this.
Android 12 introduced support for the GSMA TS.43 standard where provisioning for VoLTE, VoNR and Wi-Fi calling may be handled by Google Firebase. Currently it is very rare for carriers to be using Firebase to handle this. It is unlikely, but technically possible, that with such carriers you may be required to install sandboxed Google Play in order to obtain the former mentioned functionality where the carrier has not implemented fallback provisioning via SMS. Currently only US Cellular, Orange France, Cspire US, and Cellcom US are using this standard.
GrapheneOS includes bypasses for carrier restrictions on APN editing, tethering via USB, Ethernet, Bluetooth and Wi-Fi and the ability to disable 2G (only on 6th and 7th generation Pixel devices), actions which would not necessarily have been possible on the stock operating system.


Current Master's Assistant and MSCS student at Northeastern University. I have an extensive professional background in behavioral sciences prior to my current coursework, with a broad education in software development, database management, and project organization. My passion is breaking impossible ideas down into understandable parts via clear communication, straightforward direction, and flexible implementation. I strive to connect every project I contribute to back to the human element that guides, creates, or demands it.


{% extends 'contact/base_contact.html' %} {% block content_detail %}
for your interest in Lord Chambray, your message was sent as required.
We will reply as soon as possible.
Lord Chambray Staff


{% trans %}Database upgrade in progress!{% endtrans %}
{%- elif live_log is defined %}{% trans %}Upgrade in progress. Do not hit cancel!{% endtrans %}
{%- for event in live_log %}{{ event|safe }}{%- endfor %}{% trans %}pyClanSphere requires a database upgrade!{% endtrans %}
{% trans %}A database upgrade can become necessary when a new version of pyClanSphere or one of your plugins is installed.{% endtrans %}
{% trans %}When you click “Perform upgrade”, your database will be brought in sync with the format the installed software expects. While this is designed not to corrupt your database, you can back it up now before clicking “Perform upgrade”.{% endtrans %}
{%- if repo_ids %}{% trans %}Components that need an upgrade:{% endtrans %} {{ repo_ids|join(', ') }}
{%- endif %}


Use hashes whenever you are supplying two objects - a key and a value. A simple example would be "Name" which a key and "Patrick" which is a value.
Use the following process for creating hashes. Define the hash with the hash name like you would for any other variable. Put the key/value pairs inside squiggly lines. Put keys on the left side of the expression and values on the right-side. Lasty, don't forget to separate each key-value pair with commas.
Unlike arrays, hashes are not stored in any particular order. Hashes are retrieved using the 'key' rather than their position. The way to access a hash would be: hash_name[key]. In our example below the following would return the value '27':
Another important point to consider is that keys must be unique. Values on the other hand are allowed to repeat. There are other ways to create hashes than the method I mentioned above, but that is beyond the scope of this article. Hashes are another useful class in the Ruby programming language.


{% extends "layout.html" %} {% block content %}
Please click on the image to select the Employee's primary location.


| Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
|---|---|---|---|---|
| app/controllers/annotations_controller.rb | 83 | 47 | 36.14%
|
36.17%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 |
2 class AnnotationsController < ApplicationController |
3 |
4 # #Unecessary since protect_from_forgery not present in application_controller |
5 # #Remove authentication from create |
6 # protect_from_forgery :except => :create |
7 # skip_before_filter :verify_authenticity_token |
8 |
9 |
10 def index |
11 # Note! This is currently deactivated from routes, but is kept here |
12 # for reference. |
13 @annotations = Annotation.all |
14 respond_to do |format| |
15 format.html # index.html.erb |
16 format.json { render :json => @annotations } |
17 end |
18 end |
19 |
20 def show |
21 # It should be noted that the :id field in RESTful routing actually maps |
22 # to :uuid in our model and controller. While the :id field still exists |
23 # implicitly in our model, it's not visible to the end user, and is not |
24 # used in unit testing to locate a unique object which has no UUID, e.g. |
25 # CapturedFile and Hannotation. Since we didn't do explicit parameter |
26 # remapping in routes.rb, here the actual UUID value is stored in params[:id]. |
27 @annotation = Annotation.find_by_uuid(params[:id]) |
28 render :text => "Unknown annotation uuid.", :status => 404 and return if @annotation.nil? |
29 respond_to do |format| |
30 format.html |
31 format.json { render :json => @annotation } |
32 end |
33 end |
34 |
35 def create |
36 |
37 # Parse and validate the post parameters in the request |
38 annotation_params = params[:annotation] |
39 render :text => "Invalid data in request.", :status => 400 and return if annotation_params.nil? |
40 |
41 uuid = annotation_params[:uuid] |
42 render :text => "Annotation #{uuid} already exists.", :status => 409 and return if Annotation.exists?(:uuid => uuid) |
43 |
44 # Create the annotation, and any additional objects or values that are required |
45 @annotation = Annotation.new(annotation_params) |
46 @annotation.browser = request.env['HTTP_USER_AGENT'] |
47 @annotation.capture_time = Time.at(Float(annotation_params[:capture_time])) |
48 |
49 if<EMAIL_ADDRESS>|
50 render :text => "Failed saving annotation object.", :status => 500 and return |
51 end |
52 |
53 if request.form_data? |
54 |
55 capture_files = params[:capture] |
56 capture_files.each do |path, data| |
57 file = CapturedFile.new(:annotation => @annotation, :path => path, :content => data) |
58 if !file.save |
59 logger.warn "Failed saving capture/#{path} for annotation #{uuid}." |
60 end |
61 end |
62 |
63 # TODO: Use some configuration file for resolving the View URL. |
64 view_url = "/view/#{uuid}" |
65 |
66 redirect_to view_url and return |
67 end |
68 |
69 # Note: The recipient is assumed to be expecting the response as JSON. |
70 render :json => @annotation, :status => 201 |
71 end |
72 |
73 def destroy |
74 @annotation = Annotation.find_by_uuid(params[:id]) |
75 render :text => "Unknown annotation uuid.", :status => 404 and return if @annotation.nil? |
76 |
77 # TODO: Verify that related objects are deleted!! |
78 @annotation.destroy |
79 |
80 render :text => "Deleted." |
81 end |
82 |
83 end |
Generated on 2011-02-22 12:05:16 +0200 with rcov 0.9.8


The next package release into AWS Athena
RBloggers|RBloggers-feedburner
RAthena 1.7.1
and noctua 1.5.1
package versions have now been released to the CRAN. They both bring along several improvements with the connection to AWS Athena
, noticeably the performance speed and several creature comforts.
These packages have both been designed to reflect one another,even down to how they connect to AWS Athena
. This means that all features going forward will exist in both packages. I will refer to these packages as one, as they basically work in the same way.
Performance improvements:
Initially the packages utilised AWS Athena
SQL queries. This was to achieve all the functional requirements of the DBI
package framework. However the package would always send a SQL query to AWS Athena
which in turn would have to lift a flat file from AWS S3
, before returning the final result to R
. This means the performance of the packages would be limited and fairly slow compared to other data base backends.
The biggest change is the adoption of more functionality of the SDKs (software development kit) into AWS. The key component that has been adopted is AWS Glue
. AWS Glue
contains all of AWS Athena
table DDL’s. This means instead of going to AWS Athena
for this information AWS Glue
can be used instead.
By utilising AWS Glue
, the table meta data (column names, column types, schema hierarchy etc…) can easily be retrieved at a fraction of the time it would of taken to query AWS Athena
. Previously the DBI
function dbListTables
would send a query to AWS Athena
, this would retrieve all the tables listed in all schemas. This would take over 3 seconds. Now using AWS Glue
to retrieve the same data, it takes less than 0.5 of a second.
dplyr
When AWS Glue
is used to collect metadata around a table in AWS Athena
, a performance in dplyr::tbl
can be done. I would like to say thanks to @OssiLehtinen for developing the initial implementation as this improvement would have been overlooked.
dplyr::tbl
has two key methods when creating the initial object. The first is called SQL identifiers and this is the method that benefits from the new AWS Glue
functionality. To use SQL identifiers is fairly straight forward.
library(DBI)
library(dplyr)
library(RAthena) #Or library(noctua)
con = dbConnect(athena())
dbWriteTable(con, "iris", iris)
ident_iris = tbl(con, "iris")
dplyr
can identify the iris
table within the connected schema. When a user uses the SQL identifier method in dplyr::tbl
, AWS Glue
is called to retrieve all the meta data for dplyr
. This increases the performance from 3.66 to 0.29 seconds. The second method is called SQL sub query. This unfortunately won’t benefit from the new feature and will run in slower at 3.66 seconds.
subquery_iris = tbl(con, sql("select * from iris"))
Therefore I recommend the use of SQL identifier method when using dplyr's
interface.
Creature Comforts
AWS Athena Metadata
Due to user feature requests the packages now return more meta data around each query sent to AWS Athena
. Thus the basic level of meta data returned, is the amount of data scanned by AWS Athena
. This is formatted into a readable format depending on the amount of data scanned.
library(DBI)
library(RAthena) #Or library(noctua)
con = dbConnect(athena())
dbWriteTable(con, "iris", iris)
dbGetQuery(con, "select * from iris")
Info: (Data scanned: 860 Bytes)
sepal_length sepal_width petal_length petal_width species
1: 5.1 3.5 1.4 0.2 setosa
2: 4.9 3.0 1.4 0.2 setosa
3: 4.7 3.2 1.3 0.2 setosa
4: 4.6 3.1 1.5 0.2 setosa
5: 5.0 3.6 1.4 0.2 setosa
---
146: 6.7 3.0 5.2 2.3 virginica
147: 6.3 2.5 5.0 1.9 virginica
148: 6.5 3.0 5.2 2.0 virginica
149: 6.2 3.4 5.4 2.3 virginica
150: 5.9 3.0 5.1 1.8 virginica
However if you set the new parameter statistics
to TRUE
then all the metadata around that query is printed out like so:
dbGetQuery(con, "select * from iris", statistics = TRUE)
$EngineExecutionTimeInMillis
[1] 1568
$DataScannedInBytes
[1] 860
$DataManifestLocation
character(0)
$TotalExecutionTimeInMillis
[1] 1794
$QueryQueueTimeInMillis
[1] 209
$QueryPlanningTimeInMillis
[1] 877
$ServiceProcessingTimeInMillis
[1] 17
Info: (Data scanned: 860 Bytes)
sepal_length sepal_width petal_length petal_width species
1: 5.1 3.5 1.4 0.2 setosa
2: 4.9 3.0 1.4 0.2 setosa
3: 4.7 3.2 1.3 0.2 setosa
4: 4.6 3.1 1.5 0.2 setosa
5: 5.0 3.6 1.4 0.2 setosa
---
146: 6.7 3.0 5.2 2.3 virginica
147: 6.3 2.5 5.0 1.9 virginica
148: 6.5 3.0 5.2 2.0 virginica
149: 6.2 3.4 5.4 2.3 virginica
150: 5.9 3.0 5.1 1.8 virginica
This can also be retrieved by using dbStatistics
:
res = dbExecute(con, "select * from iris")
# return query statistic
query_stats = dbStatistics(res)
# return query results
dbFetch(res)
# Free all resources
dbClearResult(res)
RJDBC
inspired function
I have to give full credit to the package RJDBC
for inspiring me to create this function. DBI
has got a good function called dbListTables
that will list all the tables that are in AWS Athena
. However it won’t return to which schema each individual table is related to. To over come this RJDBC
has a excellent function called dbGetTables
. This function returns all the tables from AWS Athena
as a data.frame
. This has the advantage of detailing schema, table and table type. With the new integration into AWS Glue
this can be returned quickly.
dbGetTables(con)
Schema TableName TableType
1: default df_bigint EXTERNAL_TABLE
2: default iris EXTERNAL_TABLE
3: default mtcars2 EXTERNAL_TABLE
4: default nyc_taxi_2018 EXTERNAL_TABLE
This just makes it a little bit easier when working in different IDE’s for example Jupyter
.
Backend option changes
This is not really a creature comfort but it still interesting and useful. Both packages are dependent on data.table
to read data into R
. This is down to the amazing speed data.table
offers when reading files into R
. However a new package, with equally impressive read speeds, has come onto the scene called vroom
. As vroom
has been designed to only read data into R
similarly to readr
, data.table
is still used for all of the heavy lifting. However if a user wishes to use vroom
as the file parser an *_options
function has been created to enable this:
nocuta_options(file_parser = c("data.table", "vroom"))
# Or
RAthena__options(file_parser = c("data.table", "vroom"))
By setting the file_parser to vroom
then the backend will change to allow vroom's
file parser to be used instead of data.table
.
If you aren’t sure whether to use vroom
over data.table
, I draw your attention to vroom
boasting a whopping 1.40GB/sec throughput.
Statistics taken from vroom’s github readme
| package | version | time (sec) | speed-up | throughput |
|---|---|---|---|---|
| vroom | 1.1.0 | 1.14 | 58.44 | 1.40 GB/sec |
| data.table | 1.12.8 | 11.88 | 5.62 | 134.13 MB/sec |
| readr | 1.3.1 | 29.02 | 2.30 | 54.92 MB/sec |
| read.delim | 3.6.2 | 66.74 | 1.00 | 23.88 MB/sec |
RStudio Interface!
Due to the ability of AWS Glue
to retrieve metadata for AWS Athena
at speed, it has now been possible to add the interface into RStudio’s connection tab. When a connection is established:
library(DBI)
library(RAthena) #Or library(noctua)
con = dbConnect(athena())
The connection icon will as follows:
The AWS region you are connecting to will be reflected in the connection (highlighted above in the red square). This is to help users that are able to connect to multiple different AWS Athena
over different regions.
Once you have connected AWS Athena
, schema hierarchy will be displayed. In my example you can see some of the tables I have created when testing these packages.
For more information around RStudio’s connection tab please check out RStudio preview connections.
Summary
To sum up, the Rathena
and noctua
latest versions have been released to cran with all the new goodies they bring. As these packages are based on AWS SDK’s they are highly customisable. Features can easily be added to improve the packages when connecting to AWS Athena
. So please raise any feature requests / bug issues to: https://github.com/DyfanJones/RAthena and https://github.com/DyfanJones/noctua


PicSearch lets you open an image search engine directly from your iMessage conversation thread.

Now you are ready to send. You can add a message to the image if you will. Then, just press the send button.


{# This file extends Apostrophe's outerLayoutBase template, which we don't recommend overriding directly. Changes in this file, if any, are usually block overrides to modify the outer chrome, outside the main content area of the page. Most of the time you should just edit `layout.html` in the top level `views/` folder. #} {% extends "outerLayoutBase.html" %} {% block extraHead %} {# This block outputs its contents in the HTML document's
. It is a good place to put extra


DISC
{{questionIndex+1}}. {{question.question}}
Most
Least
{{answer.answer}}
Back
Next
Submit
{{name}}


This recipe comes from one of my favorite Korean TV shows (KDrama), called "Let's Eat." In episode 14 of season 2, one of the main characters, a foodie named Dae Young, explains that, "Cooking is the taste of fire." With the little ingredients left in his friends fridge, he uses the slight scorching of the heat to enhance the flavor of the fried rice. The reason we use day old rice is because it has less water in it, so when it's fried it'll get chewier, which is the texture you want. Trust me, it tastes better than it sounds!


| Name | Type | Creator | Created | Last Edited | Status | |
|---|---|---|---|---|---|---|
| {{ draft.details.title }} | {{ draft.softwareType }} | {{ draft.owner.username }} | {{ millisToDate(draft.dateCreated) }} | {{ millisToDate(draft.dateUpdated) }} | {{ draft.reviewState.replace("_", " ") }} |
Please explain to the user why the page has been rejected. The contents of your explanation will be sent directly to the user.
| Name | Type | Creator | Created | Last Edited | Status | |
|---|---|---|---|---|---|---|
| {{ amendment.details.title }} | {{ amendment.softwareType }} | {{ amendment.owner.username }} | {{ millisToDate(amendment.dateCreated) }} | {{ millisToDate(amendment.dateUpdated) }} | {{ amendment.reviewState.replace("_", " ") }} |
Please explain to the user why the page amendment has been rejected. The contents of your explanation will be sent directly to the user.
| Name | Author | |
|---|---|---|
| {{ page.details.title }} | {{ page.owner.username }} |


VIMOC's Landscape Computing REST API provides functionality for third-party software to access aggregated information and historical statistics for the sensors that form part of the Landscape Computing Architecture. This provides functionality for accessing data related to a variety of sensors (including parking sensors), and for performing queries on aggregated information about logical groups of sensors. The REST API is built upon Apache tools, and supports queries of the formats: TEXT/XML, APPLICATION/XML, and APPLICATION/JSON.
Within the Landscape Computing Architecture, sensors are grouped into logical collections, according to their geographical location. There are two main concepts used for these groupings: sites and zones.
A site is a large-scale grouping collection of sensors, corresponding to a city, campus, parking station or other location. Each site typically has its own individual management and reporting, along with a distinct user-interface instance. Each site is composed of a number of zones. These are smaller groupings, consisting of, at most, a few dozen sensors. Each zone corresponds to an individual cluster of sensors, in a well-defined geographical area.
Sensors exposed by the API are, in fact, “virtual” sensors, queried from individual physical sensors connected to nBoxes located on the Landscape Mesh. Each sensor, as seen by the API may actually correspond to a number of physical hardware sensors, with sensor processing being done on the “network edge” by nBoxes to provide more accurate, intelligent real-time data. Each zone and sensor can be queried to provide information, whether it be stored data, or calculated results.
The API Client SDK comes as a series of React.js Components.
React.js is an open source project from Facebook
The instagram application is entirely built with React.js
Components can be rendered
on the client as a traditional AJAX app (preferred)
on the server (e.g. SEO).
The SDK's components follow the ReaCall API SDK Architecture. These components are standard React components which can be embedded in any Web Application. Their properties matches the VIMOC API query parameters. For instance, the API call:
site/{site}
is realized with the following component:
React.render( <SiteForm site="{site}" />, document.getElementById('sites-form-container') ) ;
Each component features five display modes:
Each components has three key methods:
The rendering itself is performed in a different component (a view). Views are stateless (properties only) React components. For instance the Sites component renders its data using the Site view:
<SiteView key={divid} description={this.state.description} id={this.state.id} gpsCoord={this.state.gpsCoord} timeZone={this.state.timeZone} zones={this.state.zones} />
You should not modify the API call components. Over time these components will be enhanced by the VIMOC team, but should for the most part remain compatible with the corresponding view interface.
The views are the component you want to modify to adjust their output to your needs.
The overall directory structure is as follows:


Tabs
520
Total Sales
1,120
Total Visitors
| Product | Qty |
|---|---|
| Floor Lamp | 2 |
| Coffee Mug | 4 |
| Television | 1 |
| Red Carpet | 6 |
| Laptop | 3 |
234
Total Arrived
2,544
Total Sold
| Name | Price |
|---|---|
| Monitor | 4 |
| Coffee Mug | 4 |
| Television | 1 |
| Red Carpet | 6 |
| Laptop | 3 |
Pills
520
Total Sales
1,120
Total Visitors
| Product | Qty | Price |
|---|---|---|
| Floor Lamp | 2 | 3 |
| Coffee Mug | 4 | 7 |
| Television | 1 | 3 |
| Red Carpet | 6 | 5 |
| Laptop | 3 | 6 |
115
Total Sales
4,323
Total Visitors
| Product | Qty |
|---|---|
| Floor Lamp | 2 |
| Coffee Mug | 4 |
| Television | 1 |
| Red Carpet | 6 |
| Laptop | 3 |
243
Total Sales
2,734
Total Visitors
| Product | Qty |
|---|---|
| Floor Lamp | 2 |
| Coffee Mug | 4 |
| Television | 1 |
| Red Carpet | 6 |
| Laptop | 3 |


{% extends "base.html" %} {% block content %}
View all patron request below
All your customers are currently satisfied - no requests